* feat(admin): make media uploads abortable
* feat(admin): add direct multi-file media uploads
* fix(admin): refine media upload dialog
* docs: format media upload specification
* docs: simplify media upload guidance
* test(admin): follow media upload dialog flow
* test(admin): remove review-specific comment
* Update packages/admin/src/components/MediaUploadDialog.tsx
Co-authored-by: emdashbot[bot] <273199577+emdashbot[bot]@users.noreply.github.com>
* style(admin): align media drop icon color
* fix(admin): align local media upload types
* docs: correct media upload file types
* chore: mark media upload as minor
---------
Co-authored-by: emdashbot[bot] <273199577+emdashbot[bot]@users.noreply.github.com>
The request-scoped db commit() persisted the D1/DO Sessions bookmark
cookie only when isAuthenticated was true — but that flag is captured
before the route runs. Login, signup, and invite-acceptance requests
start unauthenticated and create the Astro session mid-request, so
their bookmark was discarded. The follow-up authenticated request then
read a nearest replica with no bookmark constraint and could miss the
just-created user row (auth middleware getUserById), bouncing the
brand-new user back to login.
The middleware now passes an endedAuthenticated() thunk, evaluated at
commit() time, that scans the OUTGOING cookie jar for astro-session:
Astro's session.set() writes the cookie synchronously, so a session
created during the request is visible there. Only outgoing cookies
count — falling back to the request's own Cookie header would let an
anonymous render carrying a stale session cookie overwrite a fresher
bookmark with a lagging replica's (and set a needless cookie).
Both bookmark adapters (D1, DO-SQL) honour the new signal; Hyperdrive
has no bookmark state and is unchanged.
The Environment section still taught the import.meta.env fallback chain
as the 'secrets pattern'. Since #2140, secrets are read from process.env
only — import.meta.env is statically inlined at build time, which bakes
build-machine values into the bundle and shadows runtime secrets. The
fallback chain remains correct for public build-time config, so the line
is split rather than removed.
* i18n(fr): translate in French the 89 missing keys
* example.com
Co-authored-by: emdashbot[bot] <273199577+emdashbot[bot]@users.noreply.github.com>
---------
Co-authored-by: emdashbot[bot] <273199577+emdashbot[bot]@users.noreply.github.com>
Co-authored-by: Matt Kane <mkane@cloudflare.com>
* fix(core): generate row types for repeater fields
`fieldTypeToTypeScript` had no `repeater` case, so every repeater field
fell through to `default: return "unknown"` -- while the zod side derives
a precise row schema from the same `validation.subFields` metadata.
This was an oversight rather than a decision. The emitter's switch,
including its deliberate `case "json": return "unknown"`, dates from
43fcb9a1 and predates the field type: #111 added `repeater` without
touching this file at all, so neither the zod case nor the TS case
arrived with the feature. #2458 then added the zod case and left the TS
side as it was. Type generation is now the only consumer of `subFields`
that discards it -- media-usage extraction and the admin field editor
both read it.
Consumers cannot index or iterate `unknown`, so they declare row shapes
by hand and cast to them. Those casts silence the compiler: when a
sub-field is renamed or retyped, the generated type stays `unknown`, the
cast keeps asserting the old shape, and the drift surfaces as a silently
blank render rather than a type error.
- Build an inline row type from `subFields`, reusing the existing
per-type mapping so a `select` sub-field enumerates its options and an
`image` sub-field emits the same media literal as a top-level image.
- Type a sub-field that is not required as `T | null`, since
`generateRepeaterRowSchema` applies `.nullish()` to it. A bare `T`
would trade an honest `unknown` for an unsound type.
- Keep emitting `unknown` when `subFields` is absent or empty. A repeater
with no declared rows is schema-valid, and `{}[]` would be falsely
permissive.
`fieldTypeToTypeScript` now takes a structural subset of `Field` so a
sub-field can reuse the mapping without a type assertion.
Sub-field slugs match `/^[a-z][a-z0-9_]*$/`, so they are valid bare
identifiers and need no quoting in the emitted literal.
* fix(core): emit valid repeater row types from unvalidated sub-fields
Quote member names, keep the last declaration of a duplicated slug, and
fall back to `unknown` when `subFields` is not an array.
---------
Co-authored-by: Matt Kane <mkane@cloudflare.com>
* fix(taxonomies): respect active locale in admin surfaces
Group translated definitions by logical identity before rendering admin navigation and editor choices. Scope visible term counts and cache entries to the resolved content locale.
* fix(taxonomies): preserve locale in admin term views
* ci: update query-count snapshots
* fix(admin): preserve locale sidebar active state
* fix(taxonomies): preserve exact locale updates
* test(perf): update locale query snapshots
---------
Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
* fix(scheduler): surface missed scheduled work
Persist maintenance heartbeats so authenticated editors are warned when overdue content indicates the scheduler has stopped.
* fix(scheduler): keep heartbeat writes non-fatal
A transient operator-health write must not reject maintenance that already completed successfully.
* test(scheduler): cover heartbeat upsert failures
Keep the non-fatal heartbeat contract exercised for both initial inserts and existing-row updates.
* feat(cli): detect broken scheduler wiring
Catch Cloudflare deployments that would silently miss scheduled work before they are deployed.
* fix(cli): keep doctor type-aware lint clean
* fix(cli): preserve additive doctor checks
Keep explicit database diagnosis intact, recognize Wrangler TOML, and avoid flagging Workers that do not opt into EmDash scheduled maintenance.
* fix(cli): make scheduler fixes config-aware
Keep doctor guidance copy-pasteable for Wrangler TOML users as well as JSON and JSONC sites.
* fix(cli): finish TOML doctor guidance
Keep every copy-pasteable scheduler fix and the command help accurate for all supported Wrangler formats.