From 43c5627688eb143edc83cde6bef318a884db14e7 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Tue, 7 Apr 2026 15:38:13 +0200 Subject: [PATCH] fix(core): pass field.options through to admin manifest for plugin field widgets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The manifest builder in EmDashRuntime.getManifest() only mapped field.validation.options (the legacy enum-style select widget shape) into the manifest's field entry, ignoring field.options entirely. The seed schema types SeedField.options as Record for arbitrary plugin field-widget config, the DB column exists, and SchemaRegistry correctly reads it — but the manifest builder dropped it on the floor. As a result, plugin field widgets had no way to receive their per-field configuration from the seed file. Any plugin needing per-instance config (rather than hardcoded defaults like the reference color picker) was silently broken. Pass field.options through to entry.options before the legacy validation.options mapping, and widen ManifestCollection.fields options to a union of the legacy Array<{value, label}> shape and Record so plugin widgets are first-class. Discovered while building a checkbox-grid widget for a "harvest calendar" json field — the plugin needed options.months and options.symbols from the seed schema and was receiving undefined. No test added: the manifest builder is an instance method on EmDashRuntime, and there are no existing tests in packages/core/tests that construct an EmDashRuntime. Adding the runtime test scaffolding would be a much larger change. Verified manually with a working plugin (a custom checkbox-grid field widget) — the manifest now includes the field's options object and the plugin renders correctly. Co-Authored-By: Claude Opus 4.6 (1M context) Signed-off-by: Filip Ilic --- .changeset/fix-manifest-field-options.md | 5 +++++ packages/core/src/astro/types.ts | 8 +++++++- packages/core/src/emdash-runtime.ts | 14 ++++++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 .changeset/fix-manifest-field-options.md diff --git a/.changeset/fix-manifest-field-options.md b/.changeset/fix-manifest-field-options.md new file mode 100644 index 000000000..46a7a7048 --- /dev/null +++ b/.changeset/fix-manifest-field-options.md @@ -0,0 +1,5 @@ +--- +"emdash": patch +--- + +fix(core): pass field.options through to admin manifest for plugin field widgets diff --git a/packages/core/src/astro/types.ts b/packages/core/src/astro/types.ts index e5b8b6f7c..bc4bc50a7 100644 --- a/packages/core/src/astro/types.ts +++ b/packages/core/src/astro/types.ts @@ -36,7 +36,13 @@ export interface ManifestCollection { label?: string; required?: boolean; widget?: string; - options?: Array<{ value: string; label: string }>; + /** + * Field options. Two shapes: + * - Legacy enum: `Array<{ value, label }>` for select / multiSelect widgets + * - Plugin widgets: `Record` for arbitrary per-field config + * (e.g. a checkbox grid receiving its column definitions) + */ + options?: Array<{ value: string; label: string }> | Record; } >; } diff --git a/packages/core/src/emdash-runtime.ts b/packages/core/src/emdash-runtime.ts index 810b0bbae..a1d73610a 100644 --- a/packages/core/src/emdash-runtime.ts +++ b/packages/core/src/emdash-runtime.ts @@ -1152,7 +1152,10 @@ export class EmDashRuntime { label?: string; required?: boolean; widget?: string; - options?: Array<{ value: string; label: string }>; + // Two shapes: legacy enum-style `[{ value, label }]` for select widgets, + // or arbitrary `Record` for plugin field widgets that + // need per-field config (e.g. a checkbox grid receiving its column defs). + options?: Array<{ value: string; label: string }> | Record; } > = {}; @@ -1164,7 +1167,14 @@ export class EmDashRuntime { required: field.required, }; if (field.widget) entry.widget = field.widget; - // Include select/multiSelect options from validation + // Plugin field widgets read their per-field config from `field.options`, + // which the seed schema types as `Record`. Pass it + // through to the manifest so plugin widgets in the admin SPA receive it. + if (field.options) { + entry.options = field.options; + } + // Legacy: select/multiSelect enum options live on `field.validation.options`. + // Wins over `field.options` to preserve existing behavior for enum widgets. if (field.validation?.options) { entry.options = field.validation.options.map((v) => ({ value: v,