shabbat-gate 0.4.1 → 0.4.2

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/CHANGELOG.md CHANGED
@@ -3,7 +3,26 @@
3
3
  All notable changes to this package are documented here. Format loosely follows
4
4
  [Keep a Changelog](https://keepachangelog.com/).
5
5
 
6
- ## [0.4.1] - Unreleased
6
+ ## [0.4.2] - Unreleased
7
+
8
+ ### Fixed
9
+
10
+ - **A window-list refresh during Shabbat or a holiday dropped the closure in progress, so the
11
+ site reopened mid-Shabbat.** Found 2026-09-15 on a consumer site. `fetchWindows` asked Hebcal
12
+ for a range starting *today*; on a closed day the candle lighting was yesterday, so the
13
+ response held only the havdalah, `pairWindows` (which opens a window only on candles) ignored
14
+ it, and the list had no window covering `now`. The cache is fresh for 24 hours, so a list
15
+ fetched on Friday went stale on Saturday and the first visitor after that refreshed it into
16
+ an "open" answer for the rest of Shabbat. Same for Yom Kippur and every Yom Tov day after the
17
+ first. Verified against live Hebcal: a range starting 2026-09-19 does not block Saturday noon,
18
+ one starting 2026-09-21 does not block Yom Kippur noon.
19
+
20
+ The range now starts `HEBCAL_LOOKBACK_DAYS` (4) days back, which covers the longest closure
21
+ (a two-day Rosh Hashana running into Shabbat). Past windows in the list are harmless. Applies
22
+ to the visitor-location windows too. Regression test: a fetch on Saturday noon, with Hebcal's
23
+ start-date filtering simulated, must still report blocked.
24
+
25
+ ## [0.4.1] - 2026-08-29
7
26
 
8
27
  ### Fixed
9
28
 
package/dist/hebcal.d.ts CHANGED
@@ -50,6 +50,10 @@ export declare function pairWindows(items: HebcalItem[], defaults?: {
50
50
  label: string;
51
51
  closingLabel: string;
52
52
  }): Window[];
53
+ /** How far back the Hebcal range starts. The longest closure is a two-day Rosh
54
+ * Hashana running into Shabbat, whose first candles are lit three days before
55
+ * it ends; four days covers it with a margin for the UTC date boundary. */
56
+ export declare const HEBCAL_LOOKBACK_DAYS = 4;
53
57
  export interface FetchWindowsOptions {
54
58
  /** `true` (default) = Israel single-day Yom Tov reckoning (`i=on`). `false` =
55
59
  * diaspora two-day Yom Tov reckoning (`i=off`), correct for a visitor
@@ -92,7 +96,8 @@ export declare class HebcalTimeoutError extends Error {
92
96
  constructor(timeoutMs: number);
93
97
  }
94
98
  /**
95
- * Fetches and merges Shabbat + major-holiday windows for the next ~45 days from
99
+ * Fetches and merges Shabbat + major-holiday windows from a few days back (so a
100
+ * closure already in progress is included) to ~45 days ahead, from
96
101
  * Hebcal's free public JSON API. Defaults to Israel single-day Yom Tov mode at
97
102
  * Jerusalem's timezone; pass `options` to compute windows for a visitor's own
98
103
  * location/reckoning instead (see {@link FetchWindowsOptions}).
package/dist/hebcal.js CHANGED
@@ -60,6 +60,10 @@ export function pairWindows(items, defaults) {
60
60
  function toISODate(date) {
61
61
  return date.toISOString().slice(0, 10);
62
62
  }
63
+ /** How far back the Hebcal range starts. The longest closure is a two-day Rosh
64
+ * Hashana running into Shabbat, whose first candles are lit three days before
65
+ * it ends; four days covers it with a margin for the UTC date boundary. */
66
+ export const HEBCAL_LOOKBACK_DAYS = 4;
63
67
  /** Conservative default: Hebcal normally answers in well under a second, and
64
68
  * the answer only has to be waited for on a cold cache anyway. */
65
69
  export const DEFAULT_HEBCAL_TIMEOUT_MS = 3000;
@@ -73,7 +77,8 @@ export class HebcalTimeoutError extends Error {
73
77
  }
74
78
  }
75
79
  /**
76
- * Fetches and merges Shabbat + major-holiday windows for the next ~45 days from
80
+ * Fetches and merges Shabbat + major-holiday windows from a few days back (so a
81
+ * closure already in progress is included) to ~45 days ahead, from
77
82
  * Hebcal's free public JSON API. Defaults to Israel single-day Yom Tov mode at
78
83
  * Jerusalem's timezone; pass `options` to compute windows for a visitor's own
79
84
  * location/reckoning instead (see {@link FetchWindowsOptions}).
@@ -93,8 +98,12 @@ export class HebcalTimeoutError extends Error {
93
98
  export async function fetchWindows(latitude, longitude, options = {}) {
94
99
  const israelMode = options.israelMode ?? true;
95
100
  const tzid = options.tzid ?? 'Asia/Jerusalem';
96
- const start = new Date();
97
- const end = new Date(start.getTime() + 45 * 24 * 60 * 60 * 1000);
101
+ // Start a few days back, not today: on a closed day the candle lighting that
102
+ // opened the closure was yesterday, and without it pairWindows drops the
103
+ // whole window - a refresh during Shabbat would reopen the site (2026-09-15).
104
+ const now = Date.now();
105
+ const start = new Date(now - HEBCAL_LOOKBACK_DAYS * 24 * 60 * 60 * 1000);
106
+ const end = new Date(now + 45 * 24 * 60 * 60 * 1000);
98
107
  const startParam = toISODate(start);
99
108
  const endParam = toISODate(end);
100
109
  // A specific city (geonameid) yields Hebcal's official times for that city;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shabbat-gate",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Cloudflare Pages/Workers middleware that closes a site to human visitors during Shabbat and major Jewish holidays (Israel-observance rules), while always letting search engines and AI crawlers through.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",