shabbat-gate 0.1.1 → 0.2.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/CHANGELOG.md +115 -0
- package/README.he.md +190 -90
- package/README.md +194 -91
- package/dist/hebcal.d.ts +79 -4
- package/dist/hebcal.js +98 -23
- package/dist/holdingPage.d.ts +8 -0
- package/dist/holdingPage.js +54 -34
- package/dist/index.d.ts +47 -3
- package/dist/index.js +160 -40
- package/dist/translations.d.ts +29 -0
- package/dist/translations.js +81 -0
- package/package.json +36 -35
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this package are documented here. Format loosely follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/).
|
|
5
|
+
|
|
6
|
+
## [0.2.0] - Unreleased
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- `ShabbatGateConfig.enforceVisitorLocation` - when `true`, the gate blocks a visitor during
|
|
11
|
+
Shabbat/Yom Tov in *their own* location (from Cloudflare's `request.cf` geolocation), not
|
|
12
|
+
only Israel's. The site is closed to them if it's Shabbat in Israel **or** where they are,
|
|
13
|
+
so an overseas visitor stays blocked from Israel's candle-lighting right through their own
|
|
14
|
+
local havdalah. Holidays for a visitor outside Israel use diaspora two-day Yom Tov reckoning
|
|
15
|
+
(`i=off`); Chanukah/Purim/Yom HaAtzma'ut/Chol HaMoed stay open either way. Falls back to the
|
|
16
|
+
Israel-only decision when a request has no geolocation (local `wrangler dev`, unplaceable IP).
|
|
17
|
+
Defaults to `false` (original Israel-only behavior).
|
|
18
|
+
- **Localized secondary holding-page message.** For a visitor physically outside Israel, the
|
|
19
|
+
default holding page now shows the Hebrew message, then (below a blank-line gap) a message in
|
|
20
|
+
the visitor's own browser language (from `Accept-Language`). Built-in languages: English
|
|
21
|
+
(default/fallback), French, Russian, Spanish, German, and Arabic (right-to-left).
|
|
22
|
+
Hebrew-speaking visitors and visitors
|
|
23
|
+
in Israel get no second message. Reopen time is shown in the visitor's own timezone. Works
|
|
24
|
+
independently of `enforceVisitorLocation` (whenever the site is closed and the visitor is
|
|
25
|
+
known to be abroad).
|
|
26
|
+
- New exports supporting the above: `fetchWindows` now takes an optional third `options`
|
|
27
|
+
argument (`{ israelMode?, tzid? }`) for computing a non-Israel calendar; `mergeWindows`
|
|
28
|
+
(coalesces overlapping window lists into continuous ones); `SUPPORTED_LANGUAGES`,
|
|
29
|
+
`resolveVisitorLanguage`, and the `SecondaryMessage` / `SupportedLanguage` /
|
|
30
|
+
`FetchWindowsOptions` types.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- `HoldingPageContext` gained an optional `secondary?: SecondaryMessage` field (the localized
|
|
35
|
+
block). Existing custom `renderHoldingPage` functions are unaffected - the field is optional
|
|
36
|
+
and simply ignored if unused.
|
|
37
|
+
- The default holding page now HTML-escapes `siteName` and all label fields before
|
|
38
|
+
interpolation.
|
|
39
|
+
|
|
40
|
+
## [0.1.3] - 2026-07-12
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **Windows were computed for the wrong location past the nearest Shabbat.** `fetchWindows`
|
|
45
|
+
used to call two separate Hebcal endpoints: `/shabbat` (accurate for the given
|
|
46
|
+
`latitude`/`longitude`, but - confirmed by testing live against the API - it silently
|
|
47
|
+
ignores the requested `start`/`end` range and always returns only the single nearest
|
|
48
|
+
Shabbat) and `/hebcal` for holidays (which took a hardcoded `geonameid` for Jerusalem,
|
|
49
|
+
never the coordinates passed in). Net effect: only the very next Shabbat was ever
|
|
50
|
+
correctly localized; every window after that was computed for Jerusalem regardless of
|
|
51
|
+
the site's configured location.
|
|
52
|
+
- **Duplicate/inconsistent windows around the nearest Shabbat**, a direct consequence of
|
|
53
|
+
the bug above - the two endpoints could both emit a window for the same week, a few
|
|
54
|
+
minutes apart, with nothing merging or de-duplicating them.
|
|
55
|
+
- **A holiday's Hebrew label could leak into the following, unrelated Shabbat window.**
|
|
56
|
+
`pairWindows` tracked "the most recently seen holiday item" as a running pointer. Some
|
|
57
|
+
`holiday`-category items - fast days such as Tish'a B'Av, which are `maj=on` but have no
|
|
58
|
+
candle-lighting/havdalah of their own - never got consumed into a window, so their label
|
|
59
|
+
stayed "current" and was wrongly attached to the next real window (e.g. an ordinary
|
|
60
|
+
Shabbat mislabeled with the fast day's name). Fixed by matching each window's opening
|
|
61
|
+
`candles` event to a holiday via Hebcal's own `memo` field instead of positional
|
|
62
|
+
tracking.
|
|
63
|
+
|
|
64
|
+
**Root fix for both window bugs**: `fetchWindows` now makes a single call to the
|
|
65
|
+
`/hebcal` endpoint with `ss=on` (weekly Shabbat) added alongside `maj=on` (major
|
|
66
|
+
holidays), passing `latitude`/`longitude` directly instead of a `geonameid`. This
|
|
67
|
+
returns every window in the requested range, correctly localized, already merged and
|
|
68
|
+
chronologically ordered - eliminating the two-source reconciliation that caused both bugs.
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
- `ShabbatGateConfig.bufferMinutes` - closes the site a configurable number of minutes
|
|
73
|
+
*before* candle-lighting and reopens it the same number of minutes *after* havdalah, on
|
|
74
|
+
top of the raw Hebcal window. Applied at decision time (not baked into the 24h cache), so
|
|
75
|
+
changing it takes effect immediately.
|
|
76
|
+
- `createShabbatGateForWorker(config)` - an adapter for plain Cloudflare Workers with a
|
|
77
|
+
static `assets` binding (as opposed to Pages Functions). Returns
|
|
78
|
+
`(request: Request) => Promise<Response | null>`: `null` means "let the real site
|
|
79
|
+
through", a `Response` means "serve the holding page". Shares all fail-open/caching/
|
|
80
|
+
bypass logic with `createShabbatGate` internally, so the two can't drift apart.
|
|
81
|
+
- `INTERNAL_CACHE_KEY_URL` export - the fixed internal Workers-Cache-API key this package
|
|
82
|
+
uses to cache the merged window list for ~24h. Exported so consumers doing their own
|
|
83
|
+
caching of derived data (e.g. windows with a hand-rolled buffer) can pick a different key
|
|
84
|
+
and avoid silently serving stale data for up to a day.
|
|
85
|
+
|
|
86
|
+
## [0.1.2] - 2026-07-10
|
|
87
|
+
|
|
88
|
+
### Fixed
|
|
89
|
+
|
|
90
|
+
- Holding page showed the generic literal "הדלקת נרות"/"הבדלה" as the closure reason for
|
|
91
|
+
every window, Shabbat or holiday alike (Hebcal's `candles`/`havdalah` items always carry
|
|
92
|
+
that generic text in their `hebrew` field, never the actual occasion name). Plain Shabbat
|
|
93
|
+
weeks now default to "שבת קודש" (opening) / "השבת" (closing); holiday windows pick up the
|
|
94
|
+
holiday's own Hebrew name (e.g. "ערב ראש השנה").
|
|
95
|
+
|
|
96
|
+
### Documentation
|
|
97
|
+
|
|
98
|
+
- Documented the Cloudflare Worker + `assets` binding `run_worker_first: true` gotcha:
|
|
99
|
+
without it, requests matching a static asset are served directly and the gate's `fetch`
|
|
100
|
+
handler never runs, so the site never actually closes despite looking correctly wired up.
|
|
101
|
+
Found live in production on the package's first real-world Worker (non-Pages) deployment.
|
|
102
|
+
|
|
103
|
+
## [0.1.1] - 2026-07-10
|
|
104
|
+
|
|
105
|
+
### Added
|
|
106
|
+
|
|
107
|
+
- Hebrew README (`README.he.md`), for the package's primary intended audience.
|
|
108
|
+
|
|
109
|
+
## [0.1.0] - 2026-07-10
|
|
110
|
+
|
|
111
|
+
### Added
|
|
112
|
+
|
|
113
|
+
- Initial release: bot/crawler allowlist, Hebcal Shabbat + major-holiday window fetching
|
|
114
|
+
(Israel single-day Yom Tov mode), `createShabbatGate` Pages Functions middleware,
|
|
115
|
+
bypass query param, ~24h caching via the Workers Cache API, and fail-open error handling.
|
package/README.he.md
CHANGED
|
@@ -1,90 +1,190 @@
|
|
|
1
|
-
# shabbat-gate
|
|
2
|
-
|
|
3
|
-
Middleware ל-Cloudflare Pages / Workers שסוגר אתר לגולשים אנושיים בזמן שבת וחגי ישראל
|
|
4
|
-
המרכזיים (לפי כללי שמירת שבת בישראל) - תוך מתן גישה תמידית למנועי חיפוש ולסורקי AI, כך
|
|
5
|
-
שה-SEO לא נפגע.
|
|
6
|
-
|
|
7
|
-
[English README](README.md)
|
|
8
|
-
|
|
9
|
-
## למה זה עובד ככה
|
|
10
|
-
|
|
11
|
-
- **יום טוב חד-יומי לפי ישראל, לא ספירת חו"ל.** לוח החגים נשלף מה-API החינמי של Hebcal
|
|
12
|
-
עם הפרמטר `i=on`, שקריטי - בלעדיו מתקבלת ספירת חו"ל (יום חסימה מיותר) במקום יום טוב
|
|
13
|
-
חד-יומי, כפי שנהוג בישראל.
|
|
14
|
-
- **בוטים תמיד עוברים.** רשימת אלוול רחבה, לא תלוית רישיות, של user-agent (Googlebot,
|
|
15
|
-
Bingbot, GPTBot, ClaudeBot ורבים נוספים) נבדקת ראשונה, לפני כל שאר הלוגיקה. השער משפיע
|
|
16
|
-
רק על גולשים אנושיים - סורקים ומנועי אינדוקס רואים את האתר האמיתי 24/7, כך שדירוג
|
|
17
|
-
וניראות ב-AI-search לא נפגעים מכך שהאתר "סגור".
|
|
18
|
-
- **נכשל פתוח (Fail open).** כל שגיאה (תקלת רשת, תשובת API לא תקינה, מה שלא יהיה) גורמת
|
|
19
|
-
למעבר לאתר האמיתי במקום הצגת דף שגיאה. חסימה בטעות ביום שלישי רגיל היא באג אמיתי וגלוי;
|
|
20
|
-
אי-חסימה נדירה בזמן שגיאה היא תקלה קטנה ובלתי נראית.
|
|
21
|
-
|
|
22
|
-
## התקנה
|
|
23
|
-
|
|
24
|
-
```sh
|
|
25
|
-
npm install shabbat-gate
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## שימוש
|
|
29
|
-
|
|
30
|
-
בפרויקט Cloudflare Pages, מוסיפים קובץ `functions/_middleware.ts`:
|
|
31
|
-
|
|
32
|
-
```ts
|
|
33
|
-
import { createShabbatGate } from 'shabbat-gate';
|
|
34
|
-
|
|
35
|
-
const gate = createShabbatGate({ siteName: 'שם האתר שלי' });
|
|
36
|
-
|
|
37
|
-
export const onRequest: PagesFunction = (context) => gate(context);
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
1
|
+
# shabbat-gate
|
|
2
|
+
|
|
3
|
+
Middleware ל-Cloudflare Pages / Workers שסוגר אתר לגולשים אנושיים בזמן שבת וחגי ישראל
|
|
4
|
+
המרכזיים (לפי כללי שמירת שבת בישראל) - תוך מתן גישה תמידית למנועי חיפוש ולסורקי AI, כך
|
|
5
|
+
שה-SEO לא נפגע.
|
|
6
|
+
|
|
7
|
+
[English README](README.md)
|
|
8
|
+
|
|
9
|
+
## למה זה עובד ככה
|
|
10
|
+
|
|
11
|
+
- **יום טוב חד-יומי לפי ישראל, לא ספירת חו"ל.** לוח החגים נשלף מה-API החינמי של Hebcal
|
|
12
|
+
עם הפרמטר `i=on`, שקריטי - בלעדיו מתקבלת ספירת חו"ל (יום חסימה מיותר) במקום יום טוב
|
|
13
|
+
חד-יומי, כפי שנהוג בישראל.
|
|
14
|
+
- **בוטים תמיד עוברים.** רשימת אלוול רחבה, לא תלוית רישיות, של user-agent (Googlebot,
|
|
15
|
+
Bingbot, GPTBot, ClaudeBot ורבים נוספים) נבדקת ראשונה, לפני כל שאר הלוגיקה. השער משפיע
|
|
16
|
+
רק על גולשים אנושיים - סורקים ומנועי אינדוקס רואים את האתר האמיתי 24/7, כך שדירוג
|
|
17
|
+
וניראות ב-AI-search לא נפגעים מכך שהאתר "סגור".
|
|
18
|
+
- **נכשל פתוח (Fail open).** כל שגיאה (תקלת רשת, תשובת API לא תקינה, מה שלא יהיה) גורמת
|
|
19
|
+
למעבר לאתר האמיתי במקום הצגת דף שגיאה. חסימה בטעות ביום שלישי רגיל היא באג אמיתי וגלוי;
|
|
20
|
+
אי-חסימה נדירה בזמן שגיאה היא תקלה קטנה ובלתי נראית.
|
|
21
|
+
|
|
22
|
+
## התקנה
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm install shabbat-gate
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## שימוש
|
|
29
|
+
|
|
30
|
+
בפרויקט Cloudflare Pages, מוסיפים קובץ `functions/_middleware.ts`:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { createShabbatGate } from 'shabbat-gate';
|
|
34
|
+
|
|
35
|
+
const gate = createShabbatGate({ siteName: 'שם האתר שלי' });
|
|
36
|
+
|
|
37
|
+
export const onRequest: PagesFunction = (context) => gate(context);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### שימוש עם Worker רגיל + assets binding (לא Pages)
|
|
41
|
+
|
|
42
|
+
`createShabbatGate` מחזירה handler בצורה של Pages Functions (`(context) => Response`), וזה
|
|
43
|
+
לא מתאים ל-signature של `fetch(request, env)` של Worker רגיל (אין `next()`). במקום זאת יש
|
|
44
|
+
להשתמש ב-`createShabbatGateForWorker` - היא מחזירה `null` כשצריך לתת לאתר האמיתי לעבור, ו-
|
|
45
|
+
`Response` כשצריך להציג את דף ה"סגור":
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { createShabbatGateForWorker } from 'shabbat-gate';
|
|
49
|
+
|
|
50
|
+
const gate = createShabbatGateForWorker({ siteName: 'שם האתר שלי' });
|
|
51
|
+
|
|
52
|
+
export default {
|
|
53
|
+
async fetch(request: Request, env: { ASSETS: Fetcher }) {
|
|
54
|
+
const blocked = await gate(request);
|
|
55
|
+
return blocked ?? env.ASSETS.fetch(request);
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**מוקש שמבטל את כל השער בשקט:** Cloudflare Worker עם `assets` binding מגיש כל בקשה שתואמת
|
|
61
|
+
קובץ בתיקיית ה-assets **ישירות**, בלי להריץ בכלל את ה-`fetch` handler של ה-Worker - אלא אם
|
|
62
|
+
מגדירים `run_worker_first: true`. בלי זה, קוד השער רץ ונראה מחובר נכון, הבדיקות עוברות, אבל
|
|
63
|
+
בקשות אמיתיות לעמודים (שכמעט תמיד תואמות קובץ סטטי) אף פעם לא מגיעות אליו, אז האתר בפועל
|
|
64
|
+
אף פעם לא נסגר. ב-`wrangler.jsonc`:
|
|
65
|
+
|
|
66
|
+
```jsonc
|
|
67
|
+
{
|
|
68
|
+
"assets": {
|
|
69
|
+
"directory": "./dist",
|
|
70
|
+
"binding": "ASSETS",
|
|
71
|
+
"run_worker_first": true
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## קונפיגורציה
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
export interface ShabbatGateConfig {
|
|
80
|
+
siteName: string;
|
|
81
|
+
|
|
82
|
+
/** קווי אורך/רוחב עשרוניים לחישוב זמנים. ברירת מחדל לשניהם היא ירושלים (31.7683,
|
|
83
|
+
* 35.2137) אם לא סופקו - נקודת ייחוס טובה לכל ישראל ברזולוציה הזו. */
|
|
84
|
+
latitude?: number;
|
|
85
|
+
longitude?: number;
|
|
86
|
+
|
|
87
|
+
/** שם פרמטר + ערך נדרש ב-query string שעוקפים את השער לגמרי, כדי שבעל האתר יוכל
|
|
88
|
+
* לבדוק/לתצוגה מקדימה בכל יום. חשוב לבחור ערך שלא ניתן לניחוש - זו נוחות לבדיקות,
|
|
89
|
+
* לא הרשאה אמיתית. */
|
|
90
|
+
bypassParam?: string;
|
|
91
|
+
bypassValue?: string;
|
|
92
|
+
|
|
93
|
+
/** פונקציית רינדור מותאמת אישית לדף ה"סגור", אופציונלית. ברירת המחדל היא דף בעברית,
|
|
94
|
+
* רספונסיבי למובייל, שמציג את שם האתר ומתי הוא ייפתח מחדש. `reasonLabel` ו-`closingLabel`
|
|
95
|
+
* שונים דקדוקית עבור שבת רגילה ("שבת קודש" בפתיחה מול "השבת" בסגירה) - יש להשתמש
|
|
96
|
+
* ב-`closingLabel` עבור "ניפגש שוב אחרי ___", לא לחזור על `reasonLabel`. */
|
|
97
|
+
renderHoldingPage?: (ctx: {
|
|
98
|
+
siteName: string;
|
|
99
|
+
reasonLabel: string;
|
|
100
|
+
closingLabel: string;
|
|
101
|
+
untilLabel: string;
|
|
102
|
+
/** הודעה מקומית אופציונלית שמוצגת מתחת להודעה בעברית (עם רווח), עבור גולש מחוץ
|
|
103
|
+
* לישראל, בשפת הדפדפן שלו. חסרה עבור גולשים בישראל / דוברי עברית / כשמיקום
|
|
104
|
+
* הגולש לא ידוע. */
|
|
105
|
+
secondary?: { dir: 'ltr' | 'rtl'; lines: string[] };
|
|
106
|
+
}) => string;
|
|
107
|
+
|
|
108
|
+
/** דקות לסגור את האתר *לפני* הדלקת נרות ולפתוח אותו *אחרי* הבדלה, מעל החלון הגולמי
|
|
109
|
+
* מ-Hebcal. ברירת מחדל: 0. שימושי כרפידת בטחון מול סחיפת שעון / גלישה של הרגע
|
|
110
|
+
* האחרון בדיוק בגבול החלון. */
|
|
111
|
+
bufferMinutes?: number;
|
|
112
|
+
|
|
113
|
+
/** כשמוגדר `true`, חוסם גולש גם בזמן שבת/יום-טוב *במיקום שלו עצמו* (לפי הגאו-לוקיישן
|
|
114
|
+
* של Cloudflare ב-`request.cf`), לא רק בזמן של ישראל. האתר סגור לגולש אם זו שבת
|
|
115
|
+
* בישראל *או* במקום שבו הוא נמצא - כך שגולש בחו"ל נשאר חסום מהדלקת הנרות בישראל ועד
|
|
116
|
+
* צאת השבת המקומית שלו. חגים לגולש מחוץ לישראל מחושבים לפי יום-טוב שני של גלויות
|
|
117
|
+
* (יומיים). ברירת מחדל: `false` (שער לפי ישראל בלבד, ההתנהגות המקורית). אם אין נתוני
|
|
118
|
+
* מיקום לבקשה (למשל `wrangler dev` מקומי, או IP ש-Cloudflare לא ממקם) - אותה בקשה
|
|
119
|
+
* נופלת חזרה להחלטה לפי ישראל בלבד. */
|
|
120
|
+
enforceVisitorLocation?: boolean;
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### חסימה גם לפי אזור הזמן של הגולש (`enforceVisitorLocation`)
|
|
125
|
+
|
|
126
|
+
ברירת המחדל: השער מחושב לפי לוח הזמנים של **ישראל** בלבד, לכל גולש בעולם. ברגע שיוצאת
|
|
127
|
+
שבת בישראל, האתר נפתח לכולם - גם לגולש בארה"ב שאצלו עדיין שבת.
|
|
128
|
+
|
|
129
|
+
עם `enforceVisitorLocation: true` השער הופך ל**איחוד של שתי שבתות**: האתר סגור לגולש אם
|
|
130
|
+
זו שבת/יום-טוב בישראל **או** במיקום שממנו הוא גולש. דוגמה לגולש בניו יורק: הוא נחסם כבר
|
|
131
|
+
מהדלקת הנרות בישראל (גם אם אצלו עדיין יום שישי בצהריים), ונשאר חסום ברצף עד צאת השבת
|
|
132
|
+
המקומית שלו. חגים מחושבים לו לפי חשבון גלותי (יום-טוב שני של גלויות). חנוכה, פורים, יום
|
|
133
|
+
העצמאות וחול המועד לא חוסמים - לא בישראל ולא בחו"ל.
|
|
134
|
+
|
|
135
|
+
### הודעה בשפה מקומית לגולש מחו"ל
|
|
136
|
+
|
|
137
|
+
כשגולש נמצא מחוץ לישראל, דף ה"סגור" הדיפולטי מציג קודם את ההודעה בעברית, ומתחתיה (עם
|
|
138
|
+
רווח של שתי שורות) הודעה בשפת הדפדפן שלו (לפי כותרת `Accept-Language`). שפות מובנות:
|
|
139
|
+
אנגלית (ברירת מחדל), צרפתית, רוסית, ספרדית, גרמנית, וערבית (מוצגת מימין לשמאל). גולש דובר
|
|
140
|
+
עברית או גולש בישראל לא מקבל שורה שנייה. שעת הפתיחה מוצגת לגולש מחו"ל באזור הזמן שלו. זה עובד גם ללא
|
|
141
|
+
`enforceVisitorLocation` (בכל פעם שהאתר סגור וידוע שהגולש בחו"ל).
|
|
142
|
+
|
|
143
|
+
דוגמה מלאה:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { createShabbatGate } from 'shabbat-gate';
|
|
147
|
+
|
|
148
|
+
const gate = createShabbatGate({
|
|
149
|
+
siteName: 'tehila·games',
|
|
150
|
+
latitude: 31.7683,
|
|
151
|
+
longitude: 35.2137,
|
|
152
|
+
bypassParam: 'preview',
|
|
153
|
+
bypassValue: 'letmein-9f3a7c',
|
|
154
|
+
bufferMinutes: 10,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
export const onRequest: PagesFunction = (context) => gate(context);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## איך זה עובד
|
|
161
|
+
|
|
162
|
+
1. בדיקת בוט (regex אלוול על header ה-`user-agent`) - התאמה עוברת ישירות.
|
|
163
|
+
2. בדיקת bypass - אם פרמטר ה-query וערכו תואמים, עוברים ישירות.
|
|
164
|
+
3. שליפה (עם caching לכ-24 שעות דרך Workers Cache API) של רשימת חלונות שבת וחגים
|
|
165
|
+
מאוחדת מ-Hebcal, כ-45 יום קדימה - קריאה אחת ל-endpoint `/hebcal` (`ss=on` לשבתות
|
|
166
|
+
שבועיות + `maj=on` לחגים מרכזיים), עם `latitude`/`longitude` מועברים ישירות, כך שכל
|
|
167
|
+
חלון מחושב נכון למיקום שהוגדר, לא רק החלון הקרוב ביותר.
|
|
168
|
+
4. אם הוגדר `bufferMinutes`, הוא מוחל מעל החלונות שנשלפו לפני בדיקת הזמן.
|
|
169
|
+
5. אם הוגדר `enforceVisitorLocation`, נשלף לוח זמנים שני לפי מיקום הגולש (מ-`request.cf`,
|
|
170
|
+
בחשבון גלותי לגולש מחוץ לישראל) ומאוחד עם חלונות ישראל - חוסמים אם הזמן נופל באחד
|
|
171
|
+
מהם. חלונות חופפים ממוזגים לחלון רציף אחד כדי ששעת הפתיחה המוצגת תהיה מדויקת.
|
|
172
|
+
6. אם הזמן הנוכחי נופל בתוך חלון, מוצג דף ה"סגור" (HTTP 200). אחרת, האתר האמיתי עובר.
|
|
173
|
+
7. כל שגיאה בדרך גורמת למעבר לאתר האמיתי.
|
|
174
|
+
|
|
175
|
+
## מפתח קאש פנימי
|
|
176
|
+
|
|
177
|
+
רשימת החלונות המאוחדת נשמרת בקאש תחת מפתח פנימי קבוע
|
|
178
|
+
(`https://internal.cache/shabbat-gate-windows-v1`, מיוצא בשם `INTERNAL_CACHE_KEY_URL`) לכ-24
|
|
179
|
+
שעות דרך Workers Cache API. אם הקוד שלכם עושה caching משלו לנתונים נגזרים (למשל חלונות עם
|
|
180
|
+
buffer משלכם), כדאי להשתמש במפתח אחר - שימוש חוזר במפתח הזה יגרום בשקט להחזרת נתונים ישנים
|
|
181
|
+
ולא-מעובדים למשך עד 24 שעות.
|
|
182
|
+
|
|
183
|
+
## היסטוריית שינויים
|
|
184
|
+
|
|
185
|
+
ב-[CHANGELOG.md](CHANGELOG.md) (באנגלית) מתועד מה השתנה בכל גרסה, כולל הסבר לשורש כל
|
|
186
|
+
באג שתוקן.
|
|
187
|
+
|
|
188
|
+
## רישיון
|
|
189
|
+
|
|
190
|
+
MIT
|