@tailgatefantasysports/seasonservice 0.6.0 → 0.6.1

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/SeasonService.js CHANGED
@@ -72,30 +72,26 @@ module.exports = class SeasonService {
72
72
 
73
73
  /**
74
74
  * Get the last season that finished, including all of its types.
75
- * @summary Walks backwards from `date` past every frame of the season `date` falls in, then
76
- * collects all frames of the season before it, keyed by type.
75
+ * @summary Walks backwards from `date` a whole season at a time until it reaches one whose
76
+ * every frame has ended, then collects that season's frames keyed by type.
77
77
  *
78
- * A season `date` sits inside has not finished, so it is never the answer. Skipping the
79
- * whole season rather than just the current frame matters mid-season: from a regular-season
80
- * date, stepping back one frame lands on that same season's preseason, which would report a
81
- * partial in-progress season as the previous one.
78
+ * Stepping back one *frame* is not enough. Mid-season, one frame back is the same season's
79
+ * preseason. And in the gap between a season's preseason and its regular season, the
80
+ * nearest frame behind `date` is that same season's preseason a season that has barely
81
+ * begun, not the last one to finish.
82
82
  *
83
83
  * @param {object} date - date to begin search
84
84
  * @returns {object|null} frames keyed by type, or null when no earlier season exists
85
85
  */
86
86
  getPreviousFullSeason(date) {
87
- const current = this.getSeason(date);
88
- let frame = current || this._getSeasonDirection(date, -1);
87
+ let frame = this.getSeason(date) || this._getSeasonDirection(date, -1);
88
+
89
+ while (frame && !this._isSeasonFinished(frame.season, date))
90
+ frame = this._skipSeason(frame);
91
+
89
92
  if (!frame)
90
93
  return null;
91
94
 
92
- if (current) {
93
- while (frame && frame.season === current.season)
94
- frame = this._getSeasonDirection(new Date(frame.start - 1), -1);
95
- if (!frame)
96
- return null;
97
- }
98
-
99
95
  const full = { };
100
96
  const season = frame.season;
101
97
  while (frame && frame.season === season) {
@@ -106,6 +102,33 @@ module.exports = class SeasonService {
106
102
  return full;
107
103
  }
108
104
 
105
+ /**
106
+ * Whether every configured frame of a season has ended by `date`.
107
+ * @param {string|number} season - season key into the timeframes config
108
+ * @param {object} date - js date to measure against
109
+ * @returns {boolean}
110
+ */
111
+ _isSeasonFinished(season, date) {
112
+ const frames = this.timeframes[season];
113
+ if (!frames)
114
+ return false;
115
+
116
+ return Object.values(frames).every(({ end }) => end <= date);
117
+ }
118
+
119
+ /**
120
+ * Walks backwards past every frame of `frame`'s season to the nearest frame before it.
121
+ * @param {object} frame - season frame to step back from
122
+ * @returns {object|undefined} the preceding season's latest frame, if any
123
+ */
124
+ _skipSeason(frame) {
125
+ const season = frame.season;
126
+ while (frame && frame.season === season)
127
+ frame = this._getSeasonDirection(new Date(frame.start - 1), -1);
128
+
129
+ return frame;
130
+ }
131
+
109
132
  /**
110
133
  * Returns the regular season frame for a given season year, or null if not configured.
111
134
  * @param {string|number} seasonYear
@@ -169,7 +169,11 @@ describe('GetPreviousFullSeason — real calendar', () => {
169
169
  test.each([
170
170
  ['from the 2026 preseason', new Date('2026-08-23T00:00:00Z')],
171
171
  ['from mid 2026 regular season', new Date('2026-11-01T00:00:00Z')],
172
- ['from the 2026 off-season', new Date('2026-05-01T00:00:00Z')]
172
+ ['from the 2026 off-season', new Date('2026-05-01T00:00:00Z')],
173
+ // The gap between the 2026 preseason ending and week 1 kicking off. No frame contains
174
+ // these dates, and the nearest one behind them is the 2026 preseason.
175
+ ['from the day the 2026 preseason ends', new Date('2026-09-02T00:00:00Z')],
176
+ ['from the eve of the 2026 regular season', new Date('2026-09-08T18:00:00Z')]
173
177
  ])('%s answers 2025, whole', (_tName, date) => {
174
178
  const full = configured.getPreviousFullSeason(date);
175
179
  expect(full).not.toBeNull();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailgatefantasysports/seasonservice",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Generic Season Service",
5
5
  "main": "index.js",
6
6
  "scripts": {