scschedule 3.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -472,13 +472,52 @@ const canOrderBreakfast =
472
472
 
473
473
  ## Validation Error Types
474
474
 
475
- The library uses discriminated unions for type-safe error handling:
475
+ The library uses discriminated unions for type-safe error handling. Location types (`RuleLocation`, `FieldLocation`) provide structured data for finding and highlighting errors in the UI—no path parsing required.
476
+
477
+ ```typescript
478
+ // RuleLocation - where a rule lives (used by EmptyWeekdays)
479
+ type RuleLocation =
480
+ | { type: RuleLocationType.Weekly; ruleIndex: number }
481
+ | {
482
+ type: RuleLocationType.Override
483
+ overrideIndex: number
484
+ ruleIndex: number
485
+ }
486
+
487
+ // FieldLocation - where a field lives (used by InvalidScDateFormat)
488
+ type FieldLocation =
489
+ | { type: RuleLocationType.Weekly; ruleIndex: number; field: RuleField }
490
+ | {
491
+ type: RuleLocationType.Override
492
+ overrideIndex: number
493
+ field: OverrideField
494
+ }
495
+ | {
496
+ type: RuleLocationType.Override
497
+ overrideIndex: number
498
+ ruleIndex: number
499
+ field: RuleField
500
+ }
501
+
502
+ // RuleField - rule-level fields (weekdays, from, to)
503
+ enum RuleField {
504
+ Weekdays = 'weekdays',
505
+ From = 'from',
506
+ To = 'to',
507
+ }
508
+
509
+ // OverrideField - override date range fields (from, to)
510
+ enum OverrideField {
511
+ From = 'from',
512
+ To = 'to',
513
+ }
514
+ ```
476
515
 
477
516
  ```typescript
478
517
  type ValidationError =
479
518
  | {
480
519
  issue: ValidationIssue.InvalidScDateFormat
481
- field: string
520
+ location: FieldLocation
482
521
  value: string
483
522
  expectedFormat: string
484
523
  }
@@ -509,13 +548,7 @@ type ValidationError =
509
548
  }
510
549
  | {
511
550
  issue: ValidationIssue.EmptyWeekdays
512
- location:
513
- | { type: RuleLocationType.Weekly; ruleIndex: number }
514
- | {
515
- type: RuleLocationType.Override
516
- overrideIndex: number
517
- ruleIndex: number
518
- }
551
+ location: RuleLocation
519
552
  }
520
553
  | {
521
554
  issue: ValidationIssue.OverrideWeekdaysMismatch
@@ -580,13 +613,20 @@ import type {
580
613
  AvailabilityRange,
581
614
  ValidationError,
582
615
  ValidationResult,
616
+ RuleLocation,
617
+ FieldLocation,
583
618
  SDateString,
584
619
  STimeString,
585
620
  STimestampString,
586
621
  SWeekdaysString,
587
622
  } from 'scschedule'
588
623
 
589
- import { ValidationIssue, RuleLocationType } from 'scschedule'
624
+ import {
625
+ ValidationIssue,
626
+ RuleLocationType,
627
+ RuleField,
628
+ OverrideField,
629
+ } from 'scschedule'
590
630
  ```
591
631
 
592
632
  Note: The `Weekday` enum (used in some `ValidationError` variants) is exported from `scdate`, not `scschedule`:
@@ -58,3 +58,25 @@ export declare enum RuleLocationType {
58
58
  /** The rule is in an override section */
59
59
  Override = "override"
60
60
  }
61
+ /**
62
+ * Fields within a rule (weekly or override rule) that can contain scdate
63
+ * format values. Used in validation errors for rule-level format failures.
64
+ */
65
+ export declare enum RuleField {
66
+ /** Days of the week (SMTWTFS format) */
67
+ Weekdays = "weekdays",
68
+ /** Start time */
69
+ From = "from",
70
+ /** End time */
71
+ To = "to"
72
+ }
73
+ /**
74
+ * Fields on an override's date range that can contain scdate format values.
75
+ * Used in validation errors for override-level format failures.
76
+ */
77
+ export declare enum OverrideField {
78
+ /** Start date */
79
+ From = "from",
80
+ /** End date */
81
+ To = "to"
82
+ }
package/dist/constants.js CHANGED
@@ -60,3 +60,27 @@ export var RuleLocationType;
60
60
  /** The rule is in an override section */
61
61
  RuleLocationType["Override"] = "override";
62
62
  })(RuleLocationType || (RuleLocationType = {}));
63
+ /**
64
+ * Fields within a rule (weekly or override rule) that can contain scdate
65
+ * format values. Used in validation errors for rule-level format failures.
66
+ */
67
+ export var RuleField;
68
+ (function (RuleField) {
69
+ /** Days of the week (SMTWTFS format) */
70
+ RuleField["Weekdays"] = "weekdays";
71
+ /** Start time */
72
+ RuleField["From"] = "from";
73
+ /** End time */
74
+ RuleField["To"] = "to";
75
+ })(RuleField || (RuleField = {}));
76
+ /**
77
+ * Fields on an override's date range that can contain scdate format values.
78
+ * Used in validation errors for override-level format failures.
79
+ */
80
+ export var OverrideField;
81
+ (function (OverrideField) {
82
+ /** Start date */
83
+ OverrideField["From"] = "from";
84
+ /** End date */
85
+ OverrideField["To"] = "to";
86
+ })(OverrideField || (OverrideField = {}));
@@ -1,16 +1,16 @@
1
1
  import { sDate, sTime, sWeekdays } from 'scdate';
2
- import { ValidationIssue } from '../constants.js';
2
+ import { OverrideField, RuleField, RuleLocationType, ValidationIssue, } from '../constants.js';
3
3
  /**
4
4
  * Validates that a value is a valid SDate format (YYYY-MM-DD).
5
5
  */
6
- const validateSDateValue = (value, field) => {
6
+ const validateSDateValue = (value, location) => {
7
7
  try {
8
8
  sDate(value);
9
9
  }
10
10
  catch {
11
11
  return {
12
12
  issue: ValidationIssue.InvalidScDateFormat,
13
- field,
13
+ location,
14
14
  value: String(value),
15
15
  expectedFormat: 'YYYY-MM-DD',
16
16
  };
@@ -20,14 +20,14 @@ const validateSDateValue = (value, field) => {
20
20
  /**
21
21
  * Validates that a value is a valid STime format (HH:MM).
22
22
  */
23
- const validateSTimeValue = (value, field) => {
23
+ const validateSTimeValue = (value, location) => {
24
24
  try {
25
25
  sTime(value);
26
26
  }
27
27
  catch {
28
28
  return {
29
29
  issue: ValidationIssue.InvalidScDateFormat,
30
- field,
30
+ location,
31
31
  value: String(value),
32
32
  expectedFormat: 'HH:MM',
33
33
  };
@@ -37,14 +37,14 @@ const validateSTimeValue = (value, field) => {
37
37
  /**
38
38
  * Validates that a value is a valid SWeekdays format (SMTWTFS).
39
39
  */
40
- const validateSWeekdaysValue = (value, field) => {
40
+ const validateSWeekdaysValue = (value, location) => {
41
41
  try {
42
42
  sWeekdays(value);
43
43
  }
44
44
  catch {
45
45
  return {
46
46
  issue: ValidationIssue.InvalidScDateFormat,
47
- field,
47
+ location,
48
48
  value: String(value),
49
49
  expectedFormat: 'SMTWTFS',
50
50
  };
@@ -54,13 +54,19 @@ const validateSWeekdaysValue = (value, field) => {
54
54
  /**
55
55
  * Validates both from and to times in a time range.
56
56
  */
57
- const validateTimeRange = (timeRange, fieldPrefix) => {
57
+ const validateTimeRange = (timeRange, locationBase) => {
58
58
  const errors = [];
59
- const fromError = validateSTimeValue(timeRange.from, `${fieldPrefix}.from`);
59
+ const fromError = validateSTimeValue(timeRange.from, {
60
+ ...locationBase,
61
+ field: RuleField.From,
62
+ });
60
63
  if (fromError) {
61
64
  errors.push(fromError);
62
65
  }
63
- const toError = validateSTimeValue(timeRange.to, `${fieldPrefix}.to`);
66
+ const toError = validateSTimeValue(timeRange.to, {
67
+ ...locationBase,
68
+ field: RuleField.To,
69
+ });
64
70
  if (toError) {
65
71
  errors.push(toError);
66
72
  }
@@ -69,13 +75,16 @@ const validateTimeRange = (timeRange, fieldPrefix) => {
69
75
  /**
70
76
  * Validates a rule (weekdays and time range).
71
77
  */
72
- const validateRule = (rule, fieldPrefix) => {
78
+ const validateRule = (rule, locationBase) => {
73
79
  const errors = [];
74
- const weekdaysError = validateSWeekdaysValue(rule.weekdays, `${fieldPrefix}.weekdays`);
80
+ const weekdaysError = validateSWeekdaysValue(rule.weekdays, {
81
+ ...locationBase,
82
+ field: RuleField.Weekdays,
83
+ });
75
84
  if (weekdaysError) {
76
85
  errors.push(weekdaysError);
77
86
  }
78
- errors.push(...validateTimeRange(rule, fieldPrefix));
87
+ errors.push(...validateTimeRange(rule, locationBase));
79
88
  return errors;
80
89
  };
81
90
  /**
@@ -86,22 +95,37 @@ export const validateScDateFormats = (schedule) => {
86
95
  // Validate weekly rules
87
96
  const weeklyRules = schedule.weekly === true ? [] : schedule.weekly;
88
97
  weeklyRules.forEach((rule, ruleIndex) => {
89
- errors.push(...validateRule(rule, `weekly[${String(ruleIndex)}]`));
98
+ errors.push(...validateRule(rule, {
99
+ type: RuleLocationType.Weekly,
100
+ ruleIndex,
101
+ }));
90
102
  });
91
103
  // Validate overrides
92
104
  schedule.overrides?.forEach((override, overrideIndex) => {
93
- const fromError = validateSDateValue(override.from, `overrides[${String(overrideIndex)}].from`);
105
+ const fromError = validateSDateValue(override.from, {
106
+ type: RuleLocationType.Override,
107
+ overrideIndex,
108
+ field: OverrideField.From,
109
+ });
94
110
  if (fromError) {
95
111
  errors.push(fromError);
96
112
  }
97
113
  if (override.to) {
98
- const toError = validateSDateValue(override.to, `overrides[${String(overrideIndex)}].to`);
114
+ const toError = validateSDateValue(override.to, {
115
+ type: RuleLocationType.Override,
116
+ overrideIndex,
117
+ field: OverrideField.To,
118
+ });
99
119
  if (toError) {
100
120
  errors.push(toError);
101
121
  }
102
122
  }
103
123
  override.rules.forEach((rule, ruleIndex) => {
104
- errors.push(...validateRule(rule, `overrides[${String(overrideIndex)}].rules[${String(ruleIndex)}]`));
124
+ errors.push(...validateRule(rule, {
125
+ type: RuleLocationType.Override,
126
+ overrideIndex,
127
+ ruleIndex,
128
+ }));
105
129
  });
106
130
  });
107
131
  return errors;
package/dist/types.d.ts CHANGED
@@ -1,5 +1,35 @@
1
1
  import type { SDate, STime, STimestamp, SWeekdays, Weekday } from 'scdate';
2
- import { RuleLocationType, ValidationIssue } from './constants.js';
2
+ import { OverrideField, RuleField, RuleLocationType, ValidationIssue } from './constants.js';
3
+ /**
4
+ * Location of a rule within the schedule structure. Used by validation errors
5
+ * that point to a specific rule (e.g. EmptyWeekdays).
6
+ */
7
+ export type RuleLocation = {
8
+ type: RuleLocationType.Weekly;
9
+ ruleIndex: number;
10
+ } | {
11
+ type: RuleLocationType.Override;
12
+ overrideIndex: number;
13
+ ruleIndex: number;
14
+ };
15
+ /**
16
+ * Location of a field within the schedule structure. Used by validation errors
17
+ * that point to a specific field (e.g. InvalidScDateFormat).
18
+ */
19
+ export type FieldLocation = {
20
+ type: RuleLocationType.Weekly;
21
+ ruleIndex: number;
22
+ field: RuleField;
23
+ } | {
24
+ type: RuleLocationType.Override;
25
+ overrideIndex: number;
26
+ field: OverrideField;
27
+ } | {
28
+ type: RuleLocationType.Override;
29
+ overrideIndex: number;
30
+ ruleIndex: number;
31
+ field: RuleField;
32
+ };
3
33
  /**
4
34
  * String in YYYY-MM-DD format representing a date.
5
35
  */
@@ -98,8 +128,8 @@ export type ValidationError = {
98
128
  * (SDate, STime, SWeekdays, or STimestamp)
99
129
  */
100
130
  issue: ValidationIssue.InvalidScDateFormat;
101
- /** Path to the field with invalid format (e.g., 'weekly[0].weekdays') */
102
- field: string;
131
+ /** Location of the field with invalid format */
132
+ location: FieldLocation;
103
133
  /** The invalid value that was provided */
104
134
  value: string;
105
135
  /** The expected format (e.g., 'SMTWTFS', 'HH:MM', 'YYYY-MM-DD') */
@@ -110,14 +140,7 @@ export type ValidationError = {
110
140
  */
111
141
  issue: ValidationIssue.EmptyWeekdays;
112
142
  /** Location of the rule with empty weekdays */
113
- location: {
114
- type: RuleLocationType.Weekly;
115
- ruleIndex: number;
116
- } | {
117
- type: RuleLocationType.Override;
118
- overrideIndex: number;
119
- ruleIndex: number;
120
- };
143
+ location: RuleLocation;
121
144
  } | {
122
145
  /**
123
146
  * An override has weekdays that don't match any actual dates in the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scschedule",
3
- "version": "3.1.0",
3
+ "version": "4.0.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dist/index.js"
@@ -20,7 +20,7 @@
20
20
  "test": "vitest run"
21
21
  },
22
22
  "dependencies": {
23
- "scdate": "3.1.0"
23
+ "scdate": "4.0.0"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@eslint/js": "^9.39.2",