Skip to content

Commit 69e741f

Browse files
rita-codesclaude
andcommitted
[scheduler] Validate the FREQ value in parseRRule
`parseRRule` cast the RRULE-string `FREQ` straight to the union without checking it, and the object-input branch validated nothing. An unsupported value like `FREQ=HOURLY` passed parsing and failed later with a message disconnected from the input. Validate `freq` against DAILY/WEEKLY/MONTHLY/YEARLY in both branches and throw a clear `MUI X Scheduler:` error naming the offending value. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 166776b commit 69e741f

3 files changed

Lines changed: 36 additions & 2 deletions

File tree

docs/public/static/error-codes.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,5 +283,6 @@
283283
"283": "MUI X Scheduler: TitleColumnWidthProvider is missing.",
284284
"284": "MUI X Data Grid: Nested lazy loading does not support unknown children count for now.\nIf this is a use-case that you are interested in, please open an issue: https://github.com/mui/mui-x/issues/new?template=2.feature.yml",
285285
"285": "MUI X Data Grid: Row count is unknown. Please provide a valid row count for lazy loading to work.",
286-
"286": "MUI X Scheduler: useSharedComponentsStyledContext must be used within a SharedComponentsStyledContext.Provider. The shared internal components require the product to inject their utility classes. Ensure the component is rendered inside an EventCalendar, EventCalendarPremium, or EventTimelinePremium component, a standalone view, or another component that provides SharedComponentsStyledContext."
286+
"286": "MUI X Scheduler: useSharedComponentsStyledContext must be used within a SharedComponentsStyledContext.Provider. The shared internal components require the product to inject their utility classes. Ensure the component is rendered inside an EventCalendar, EventCalendarPremium, or EventTimelinePremium component, a standalone view, or another component that provides SharedComponentsStyledContext.",
287+
"287": "MUI X Scheduler: Invalid FREQ value \"%s\". The frequency must be one of DAILY, WEEKLY, MONTHLY, or YEARLY. Provide a supported frequency value."
287288
}

packages/x-scheduler-internals-premium/src/internals/utils/recurring-events/rRuleString.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,20 @@ describe('recurring-events/rRuleString', () => {
115115
);
116116
});
117117

118+
it('should throw when FREQ has an unsupported value', () => {
119+
expect(() => parseRRule(adapter, 'FREQ=HOURLY', 'default')).to.throw(
120+
'MUI X Scheduler: Invalid FREQ value "HOURLY". The frequency must be one of DAILY, WEEKLY, MONTHLY, or YEARLY. Provide a supported frequency value.',
121+
);
122+
});
123+
124+
it('should throw when the object input has an unsupported freq value', () => {
125+
expect(() =>
126+
parseRRule(adapter, { freq: 'HOURLY' as SchedulerEventRecurrenceRule['freq'] }, 'default'),
127+
).to.throw(
128+
'MUI X Scheduler: Invalid FREQ value "HOURLY". The frequency must be one of DAILY, WEEKLY, MONTHLY, or YEARLY. Provide a supported frequency value.',
129+
);
130+
});
131+
118132
it('should throw when the RRULE contains unsupported properties', () => {
119133
expect(() => parseRRule(adapter, 'FREQ=DAILY;FOO=bar', 'default')).to.throw(
120134
'MUI X Scheduler: Unsupported RRULE property "FOO". Supported properties are: FREQ, INTERVAL, BYDAY, BYMONTHDAY, BYMONTH, UNTIL, COUNT. Remove or replace the unsupported property.',

packages/x-scheduler-internals-premium/src/internals/utils/recurring-events/rRuleString.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,31 @@ const SUPPORTED_RRULE_KEYS = new Set([
1818
'COUNT',
1919
]);
2020

21+
const SUPPORTED_FREQUENCIES = new Set<SchedulerProcessedEventRecurrenceRule['freq']>([
22+
'DAILY',
23+
'WEEKLY',
24+
'MONTHLY',
25+
'YEARLY',
26+
]);
27+
28+
function validateFreq(freq: string): SchedulerProcessedEventRecurrenceRule['freq'] {
29+
if (!SUPPORTED_FREQUENCIES.has(freq as SchedulerProcessedEventRecurrenceRule['freq'])) {
30+
throw new Error(
31+
`MUI X Scheduler: Invalid FREQ value "${freq}". ` +
32+
'The frequency must be one of DAILY, WEEKLY, MONTHLY, or YEARLY. ' +
33+
'Provide a supported frequency value.',
34+
);
35+
}
36+
return freq as SchedulerProcessedEventRecurrenceRule['freq'];
37+
}
38+
2139
export function parseRRule(
2240
adapter: Adapter,
2341
input: string | SchedulerEventRecurrenceRule,
2442
timezone: TemporalTimezone,
2543
): SchedulerProcessedEventRecurrenceRule {
2644
if (typeof input === 'object') {
45+
validateFreq(input.freq);
2746
if (input.until != null) {
2847
return {
2948
...input,
@@ -72,7 +91,7 @@ export function parseRRule(
7291
}
7392

7493
const rrule: SchedulerProcessedEventRecurrenceRule = {
75-
freq: rruleObject.FREQ as SchedulerProcessedEventRecurrenceRule['freq'],
94+
freq: validateFreq(rruleObject.FREQ),
7695
};
7796

7897
if (rruleObject.INTERVAL) {

0 commit comments

Comments
 (0)