Skip to content

Commit b1b1002

Browse files
committed
fix(spec): make GanttConfigSchema forward-compatible via .passthrough()
The gantt renderer (objectui plugin-gantt) keeps adding view-config knobs (lockField, defaultCollapsedDepth, ...) ahead of this schema. The console validates the view config against a bundled copy of GanttConfigSchema before handing it to the renderer, so any field not declared here is stripped -- every new renderer knob otherwise needs a spec release + console rebuild to take effect. .passthrough() lets unknown fields reach the renderer, decoupling renderer releases from spec releases. Known fields keep their validation. Adds a forward-compat test asserting unknown fields survive parse.
1 parent 163fbd0 commit b1b1002

3 files changed

Lines changed: 34 additions & 1 deletion

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
fix(spec): make `GanttConfigSchema` forward-compatible via `.passthrough()`.
6+
7+
The gantt renderer (objectui plugin-gantt) keeps adding view-config knobs
8+
(e.g. `lockField`, `defaultCollapsedDepth`) ahead of this schema. Without
9+
passthrough, the console — which validates the view config against a bundled
10+
copy of this schema before handing it to the renderer — strips any field not
11+
declared here, so every new renderer knob needs a spec release + console
12+
rebuild before it can take effect. Adding `.passthrough()` lets unknown fields
13+
flow through to the renderer, decoupling renderer releases from spec releases.
14+
Known fields keep their validation; the renderer still only reads what it
15+
understands.

packages/spec/src/ui/view.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,20 @@ describe('GanttConfigSchema', () => {
237237
expect(() => GanttConfigSchema.parse(config)).not.toThrow();
238238
expect(GanttConfigSchema.parse(config)).toMatchObject({ parentField: 'parent_id', typeField: 'row_type' });
239239
});
240+
241+
it('should passthrough unknown renderer fields ahead of this schema', () => {
242+
const config = {
243+
startDateField: 'start_date',
244+
endDateField: 'end_date',
245+
titleField: 'name',
246+
// Newer renderer knobs not yet declared here (e.g. objectui plugin-gantt).
247+
lockField: 'is_locked',
248+
defaultCollapsedDepth: 2,
249+
};
250+
251+
expect(() => GanttConfigSchema.parse(config)).not.toThrow();
252+
expect(GanttConfigSchema.parse(config)).toMatchObject({ lockField: 'is_locked', defaultCollapsedDepth: 2 });
253+
});
240254
});
241255

242256
describe('ListViewSchema', () => {

packages/spec/src/ui/view.zod.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,11 @@ export const GanttConfigSchema = lazySchema(() => z.object({
427427
])).optional().describe('Fields to surface in the hover tooltip, in display order'),
428428
quickFilters: z.array(GanttQuickFilterSchema).optional().describe('Multi-select filter dropdowns rendered above the chart'),
429429
autoZoomToFilter: z.boolean().optional().describe('When true (default), filtering zooms the range to the filtered tasks'),
430-
}));
430+
// Forward-compatible: the gantt renderer (objectui plugin-gantt) keeps adding
431+
// config knobs (e.g. lockField / defaultCollapsedDepth) ahead of this schema.
432+
// Passthrough lets those extra fields reach the renderer instead of being
433+
// stripped here, so a renderer release no longer has to wait on a spec release.
434+
}).passthrough());
431435

432436
/**
433437
* Navigation Mode Enum

0 commit comments

Comments
 (0)