@khorsheed/dsh-reader 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/README.en.md +90 -0
- package/README.i18n.yaml +6 -0
- package/README.md +90 -0
- package/cordis.patch.yml +13 -0
- package/lib/client.js +15119 -0
- package/lib/index.js +3660 -0
- package/lib/invariant.js +38 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +1738 -0
- package/lib/typert.remote-client.d.ts +82 -0
- package/lib/typert.remote-client.js +1115 -0
- package/lib/types/arxiv.d.ts +47 -0
- package/lib/types/arxiv.js +76 -0
- package/lib/types/client/ReaderPane.d.ts +71 -0
- package/lib/types/client/ReaderPane.js +3135 -0
- package/lib/types/client/contract.d.ts +254 -0
- package/lib/types/client/contract.js +1 -0
- package/lib/types/client/definition.d.ts +27 -0
- package/lib/types/client/definition.js +32 -0
- package/lib/types/client/extract-article.d.ts +102 -0
- package/lib/types/client/extract-article.js +1024 -0
- package/lib/types/client/icons.d.ts +27 -0
- package/lib/types/client/icons.js +11 -0
- package/lib/types/client/index.d.ts +34 -0
- package/lib/types/client/index.js +222 -0
- package/lib/types/client/locales.d.ts +391 -0
- package/lib/types/client/locales.js +382 -0
- package/lib/types/client/parse-rss.d.ts +69 -0
- package/lib/types/client/parse-rss.js +656 -0
- package/lib/types/client/quote.d.ts +89 -0
- package/lib/types/client/quote.js +119 -0
- package/lib/types/client/selectors.d.ts +167 -0
- package/lib/types/client/selectors.js +413 -0
- package/lib/types/client/session.d.ts +171 -0
- package/lib/types/client/session.js +223 -0
- package/lib/types/client/store.d.ts +181 -0
- package/lib/types/client/store.js +226 -0
- package/lib/types/client/translate.d.ts +379 -0
- package/lib/types/client/translate.js +873 -0
- package/lib/types/index.d.ts +48 -0
- package/lib/types/index.js +25 -0
- package/lib/types/invariant.d.ts +29 -0
- package/lib/types/invariant.js +38 -0
- package/lib/types/link-resolvers.d.ts +107 -0
- package/lib/types/link-resolvers.js +299 -0
- package/lib/types/remote.d.ts +224 -0
- package/lib/types/remote.js +275 -0
- package/lib/types/schedule.d.ts +78 -0
- package/lib/types/schedule.js +114 -0
- package/lib/types/service.d.ts +633 -0
- package/lib/types/service.js +1697 -0
- package/lib/types/store.d.ts +224 -0
- package/lib/types/store.js +916 -0
- package/lib/types/types.d.ts +710 -0
- package/lib/types/types.js +182 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +128 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The daily-refresh clock: pure date math, deliberately separated from the
|
|
3
|
+
* service that arms it.
|
|
4
|
+
*
|
|
5
|
+
* There is no host scheduler to hang a "refresh every morning" job on — the
|
|
6
|
+
* host's `ctx.timer` is fiber-scoped `timeout`/`interval`/`throttle`/`debounce`
|
|
7
|
+
* only, and `dsh-schedule` is agent-session reminders rather than a service a
|
|
8
|
+
* plugin may schedule against. So the plugin owns a `setTimeout` and the only
|
|
9
|
+
* interesting part is deciding *when* — which is what lives here, as functions
|
|
10
|
+
* that take a `now` and are therefore testable without a clock.
|
|
11
|
+
*
|
|
12
|
+
* @module @khorsheed/dsh-reader/schedule
|
|
13
|
+
*/
|
|
14
|
+
/** Milliseconds in one day. */
|
|
15
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
16
|
+
/**
|
|
17
|
+
* Parse an `HH:MM` string into hours and minutes.
|
|
18
|
+
*
|
|
19
|
+
* A malformed value falls back to the caller's default rather than throwing: a
|
|
20
|
+
* hand-edited state file must not be able to break the refresh loop.
|
|
21
|
+
*
|
|
22
|
+
* @param value - the configured time of day.
|
|
23
|
+
* @param fallback - the value to use when `value` is unusable.
|
|
24
|
+
* @returns the parsed hour and minute.
|
|
25
|
+
*/
|
|
26
|
+
export function parseTimeOfDay(value, fallback) {
|
|
27
|
+
return parseOrFallback(value) ?? parseOrFallback(fallback) ?? { hour: 10, minute: 0 };
|
|
28
|
+
}
|
|
29
|
+
/** Parse one candidate, or `undefined` when it is not a valid `HH:MM`. */
|
|
30
|
+
function parseOrFallback(value) {
|
|
31
|
+
if (value === undefined)
|
|
32
|
+
return undefined;
|
|
33
|
+
const match = /^(\d{1,2}):(\d{2})$/.exec(value.trim());
|
|
34
|
+
if (match === null)
|
|
35
|
+
return undefined;
|
|
36
|
+
const hour = Number(match[1]);
|
|
37
|
+
const minute = Number(match[2]);
|
|
38
|
+
if (!Number.isFinite(hour) || !Number.isFinite(minute))
|
|
39
|
+
return undefined;
|
|
40
|
+
if (hour < 0 || hour > 23 || minute < 0 || minute > 59)
|
|
41
|
+
return undefined;
|
|
42
|
+
return { hour, minute };
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The next wall-clock occurrence of `timeOfDay` strictly after `now`.
|
|
46
|
+
*
|
|
47
|
+
* Computed through the local-time constructor rather than by adding a fixed
|
|
48
|
+
* day length, so a DST shift moves the refresh to the same wall-clock time
|
|
49
|
+
* instead of drifting an hour.
|
|
50
|
+
*
|
|
51
|
+
* @param now - the reference instant.
|
|
52
|
+
* @param timeOfDay - the configured local time.
|
|
53
|
+
* @returns the next occurrence.
|
|
54
|
+
*/
|
|
55
|
+
export function nextOccurrence(now, timeOfDay) {
|
|
56
|
+
const { hour, minute } = parseTimeOfDay(timeOfDay, '10:00');
|
|
57
|
+
const candidate = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hour, minute, 0, 0);
|
|
58
|
+
if (candidate.getTime() > now.getTime())
|
|
59
|
+
return candidate;
|
|
60
|
+
// Already past today: step to tomorrow through the constructor so the local
|
|
61
|
+
// calendar does the arithmetic (month ends, DST, leap days).
|
|
62
|
+
return new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, hour, minute, 0, 0);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The most recent occurrence of `timeOfDay` at or before `now` — the deadline
|
|
66
|
+
* a catch-up refresh compares against.
|
|
67
|
+
*
|
|
68
|
+
* @param now - the reference instant.
|
|
69
|
+
* @param timeOfDay - the configured local time.
|
|
70
|
+
* @returns the most recent occurrence.
|
|
71
|
+
*/
|
|
72
|
+
export function previousOccurrence(now, timeOfDay) {
|
|
73
|
+
const { hour, minute } = parseTimeOfDay(timeOfDay, '10:00');
|
|
74
|
+
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hour, minute, 0, 0);
|
|
75
|
+
if (today.getTime() <= now.getTime())
|
|
76
|
+
return today;
|
|
77
|
+
return new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1, hour, minute, 0, 0);
|
|
78
|
+
}
|
|
79
|
+
/** Delay to the next occurrence, clamped to Node's timer ceiling. */
|
|
80
|
+
export const MAX_TIMEOUT_MS = 2_147_483_647;
|
|
81
|
+
/**
|
|
82
|
+
* Whether a boot should refresh immediately because the last run missed its
|
|
83
|
+
* slot — the thing that makes "daily refresh" true on a machine that was
|
|
84
|
+
* asleep or whose process restarted.
|
|
85
|
+
*
|
|
86
|
+
* @param lastRun - the last completed refresh, if any.
|
|
87
|
+
* @param now - the current instant.
|
|
88
|
+
* @param timeOfDay - the configured local time.
|
|
89
|
+
* @param enabled - whether the schedule is on at all.
|
|
90
|
+
* @returns true when a catch-up run is due.
|
|
91
|
+
*/
|
|
92
|
+
export function isCatchUpDue(lastRun, now, timeOfDay, enabled) {
|
|
93
|
+
if (!enabled)
|
|
94
|
+
return false;
|
|
95
|
+
// Never refreshed: the first refresh belongs to the user's first action or to
|
|
96
|
+
// the next slot, not to a boot-time stampede of every configured feed.
|
|
97
|
+
if (lastRun === undefined)
|
|
98
|
+
return false;
|
|
99
|
+
return previousOccurrence(now, timeOfDay).getTime() > lastRun.getTime();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The timer delay for the next occurrence, capped so a scheduler survives
|
|
103
|
+
* dates beyond the 32-bit millisecond limit.
|
|
104
|
+
*
|
|
105
|
+
* @param now - the reference instant.
|
|
106
|
+
* @param timeOfDay - the configured local time.
|
|
107
|
+
* @returns the delay in milliseconds.
|
|
108
|
+
*/
|
|
109
|
+
export function delayUntilNext(now, timeOfDay) {
|
|
110
|
+
const delta = nextOccurrence(now, timeOfDay).getTime() - now.getTime();
|
|
111
|
+
return Math.min(Math.max(0, delta), MAX_TIMEOUT_MS);
|
|
112
|
+
}
|
|
113
|
+
/** Exposed for tests that want to assert a day's worth of arithmetic. */
|
|
114
|
+
export { DAY_MS };
|