@hardlydifficult/poller 1.0.24 → 1.0.26
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 +48 -122
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/watch.d.ts +17 -0
- package/dist/watch.d.ts.map +1 -0
- package/dist/watch.js +141 -0
- package/dist/watch.js.map +1 -0
- package/package.json +2 -2
- package/dist/Poller.d.ts +0 -35
- package/dist/Poller.d.ts.map +0 -1
- package/dist/Poller.js +0 -158
- package/dist/Poller.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @hardlydifficult/poller
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Opinionated polling with one entrypoint: `watch()`.
|
|
4
|
+
|
|
5
|
+
The package starts immediately, emits only when the value changes, and keeps the returned handle small.
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
@@ -10,149 +12,73 @@ npm install @hardlydifficult/poller
|
|
|
10
12
|
|
|
11
13
|
## Quick Start
|
|
12
14
|
|
|
13
|
-
```
|
|
14
|
-
import {
|
|
15
|
+
```ts
|
|
16
|
+
import { watch } from "@hardlydifficult/poller";
|
|
15
17
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
onChange: (user, previousUser) => {
|
|
22
|
-
console.log("User changed:", user, previousUser);
|
|
18
|
+
const userWatcher = await watch({
|
|
19
|
+
everyMs: 5_000,
|
|
20
|
+
read: () => fetch("/api/user").then((r) => r.json()),
|
|
21
|
+
onChange: (user, previous) => {
|
|
22
|
+
console.log("User changed", user, previous);
|
|
23
23
|
},
|
|
24
|
-
intervalMs: 5000,
|
|
25
24
|
});
|
|
26
25
|
|
|
27
|
-
await
|
|
28
|
-
|
|
29
|
-
poller.stop();
|
|
26
|
+
await userWatcher.refresh();
|
|
27
|
+
userWatcher.stop();
|
|
30
28
|
```
|
|
31
29
|
|
|
32
|
-
##
|
|
33
|
-
|
|
34
|
-
The `Poller` class supports two constructor styles: a modern options-based approach and a deprecated positional constructor for backward compatibility.
|
|
35
|
-
|
|
36
|
-
### Options-based constructor (recommended)
|
|
30
|
+
## API
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
import { Poller } from "@hardlydifficult/poller";
|
|
32
|
+
### `watch(options)`
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
fetch: async () => fetch("/api/data").then(r => r.json()),
|
|
43
|
-
onChange: (current, previous) => console.log("Changed:", current),
|
|
44
|
-
intervalMs: 3000,
|
|
45
|
-
debounceMs: 1000, // optional, defaults to 1000
|
|
46
|
-
onError: (error) => console.error("Poll error:", error), // optional
|
|
47
|
-
comparator: (curr, prev) => curr.id === prev?.id, // optional
|
|
48
|
-
});
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
| Option | Type | Description |
|
|
52
|
-
|--------|------|-------------|
|
|
53
|
-
| `fetch` | `() => Promise<T>` | Async function to fetch data |
|
|
54
|
-
| `onChange` | `(current: T, previous: T \| undefined) => void` | Callback when data changes |
|
|
55
|
-
| `intervalMs` | `number` | Polling interval in milliseconds |
|
|
56
|
-
| `debounceMs` | `number` | Debounce delay for manual triggers (default: `1000`) |
|
|
57
|
-
| `onError` | `(error: unknown) => void` | Error handler (optional) |
|
|
58
|
-
| `comparator` | `(current: T, previous: T \| undefined) => boolean` | Custom change detection (default: deep equality) |
|
|
59
|
-
|
|
60
|
-
### Deprecated positional constructor
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
const poller = new Poller(
|
|
64
|
-
async () => fetch("/api/data").then(r => r.json()),
|
|
65
|
-
(current, previous) => console.log("Changed:", current),
|
|
66
|
-
3000,
|
|
67
|
-
(error) => console.error("Poll error:", error)
|
|
68
|
-
);
|
|
69
|
-
```
|
|
34
|
+
Starts reading immediately and resolves after the first read attempt completes.
|
|
70
35
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
### `stop()`
|
|
83
|
-
Stops all timers and prevents further polling.
|
|
84
|
-
|
|
85
|
-
```typescript
|
|
86
|
-
poller.stop();
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### `trigger(debounceMs?)`
|
|
90
|
-
Manually triggers a poll, debouncing multiple calls.
|
|
91
|
-
|
|
92
|
-
```typescript
|
|
93
|
-
poller.trigger(); // Uses default debounceMs
|
|
94
|
-
poller.trigger(2000); // Override debounce delay
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Change Detection
|
|
98
|
-
|
|
99
|
-
By default, the `Poller` uses deep equality to detect changes, supporting primitives, arrays, and plain objects—even when new references are returned.
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
const poller = Poller.create({
|
|
103
|
-
fetch: async () => ({ count: 42 }),
|
|
104
|
-
onChange: (data, prev) => console.log("Changed:", data),
|
|
105
|
-
intervalMs: 2000,
|
|
36
|
+
```ts
|
|
37
|
+
const watcher = await watch({
|
|
38
|
+
everyMs: 30_000,
|
|
39
|
+
read: () => fetch("/api/data").then((r) => r.json()),
|
|
40
|
+
onChange: (current, previous) => {
|
|
41
|
+
console.log("Changed:", current, previous);
|
|
42
|
+
},
|
|
43
|
+
onError: (error) => {
|
|
44
|
+
console.error("Read failed:", error.message);
|
|
45
|
+
},
|
|
46
|
+
isEqual: (current, previous) => current.id === previous?.id,
|
|
106
47
|
});
|
|
107
|
-
|
|
108
|
-
// Even if fetch returns a new object with same content, onChange won't fire
|
|
109
48
|
```
|
|
110
49
|
|
|
111
|
-
|
|
50
|
+
Options:
|
|
112
51
|
|
|
113
|
-
|
|
52
|
+
- `read: () => Promise<T>`
|
|
53
|
+
- `onChange: (current: T, previous: T | undefined) => void`
|
|
54
|
+
- `everyMs: number`
|
|
55
|
+
- `isEqual?: (current: T, previous: T | undefined) => boolean`
|
|
56
|
+
- `onError?: (error: Error) => void`
|
|
114
57
|
|
|
115
|
-
|
|
116
|
-
const poller = Poller.create({
|
|
117
|
-
fetch: async () => ({ id: 1, name: "Alice" }),
|
|
118
|
-
onChange: (data, prev) => console.log("Changed:", data.name),
|
|
119
|
-
intervalMs: 2000,
|
|
120
|
-
comparator: (current, previous) => current.name === previous?.name,
|
|
121
|
-
});
|
|
122
|
-
```
|
|
58
|
+
### `watcher.current`
|
|
123
59
|
|
|
124
|
-
|
|
60
|
+
The last emitted value. This stays `undefined` until a read succeeds and is accepted as changed.
|
|
125
61
|
|
|
126
|
-
|
|
62
|
+
### `watcher.refresh()`
|
|
127
63
|
|
|
128
|
-
|
|
129
|
-
const poller = Poller.create({
|
|
130
|
-
fetch: async () => { throw new Error("Network issue"); },
|
|
131
|
-
onChange: () => {},
|
|
132
|
-
intervalMs: 1000,
|
|
133
|
-
onError: (err) => console.warn("Caught error:", err),
|
|
134
|
-
});
|
|
64
|
+
Runs a read immediately and returns the current emitted value. If a read is already in flight, the same promise is reused.
|
|
135
65
|
|
|
136
|
-
|
|
66
|
+
```ts
|
|
67
|
+
const current = await watcher.refresh();
|
|
137
68
|
```
|
|
138
69
|
|
|
139
|
-
|
|
70
|
+
### `watcher.stop()`
|
|
140
71
|
|
|
141
|
-
|
|
72
|
+
Stops the interval and makes future `refresh()` calls a no-op.
|
|
142
73
|
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
fetch: async () => {
|
|
146
|
-
await new Promise(r => setTimeout(r, 2000)); // Simulate slow fetch
|
|
147
|
-
return "data";
|
|
148
|
-
},
|
|
149
|
-
onChange: () => {},
|
|
150
|
-
intervalMs: 1000, // Won't trigger overlapping fetch
|
|
151
|
-
});
|
|
74
|
+
```ts
|
|
75
|
+
watcher.stop();
|
|
152
76
|
```
|
|
153
77
|
|
|
154
|
-
##
|
|
78
|
+
## Behavior
|
|
155
79
|
|
|
156
|
-
-
|
|
157
|
-
-
|
|
158
|
-
-
|
|
80
|
+
- The first successful read calls `onChange(current, undefined)`.
|
|
81
|
+
- Reads never overlap.
|
|
82
|
+
- Deep equality is the default change detection for primitives, arrays, and plain objects.
|
|
83
|
+
- Polling continues after read failures.
|
|
84
|
+
- If `onError` is omitted, errors are logged with `console.error`.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { watch, type WatchHandle, type WatchOptions } from "./watch.js";
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
var
|
|
5
|
-
Object.defineProperty(exports, "
|
|
3
|
+
exports.watch = void 0;
|
|
4
|
+
var watch_js_1 = require("./watch.js");
|
|
5
|
+
Object.defineProperty(exports, "watch", { enumerable: true, get: function () { return watch_js_1.watch; } });
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uCAAwE;AAA/D,iGAAA,KAAK,OAAA"}
|
package/dist/watch.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Small opinionated polling utility that reads periodically and emits only when the value changes. */
|
|
2
|
+
export interface WatchOptions<T> {
|
|
3
|
+
readonly read: () => Promise<T>;
|
|
4
|
+
readonly onChange: (current: T, previous: T | undefined) => void;
|
|
5
|
+
readonly everyMs: number;
|
|
6
|
+
readonly isEqual?: (current: T, previous: T | undefined) => boolean;
|
|
7
|
+
readonly onError?: (error: Error) => void;
|
|
8
|
+
}
|
|
9
|
+
/** Live watcher handle returned by {@link watch}. */
|
|
10
|
+
export interface WatchHandle<T> {
|
|
11
|
+
readonly current: T | undefined;
|
|
12
|
+
stop(): void;
|
|
13
|
+
refresh(): Promise<T | undefined>;
|
|
14
|
+
}
|
|
15
|
+
/** Starts watching immediately and resolves after the first read attempt completes. */
|
|
16
|
+
export declare function watch<T>(options: WatchOptions<T>): Promise<WatchHandle<T>>;
|
|
17
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"AAAA,uGAAuG;AACvG,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,CAAC;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,OAAO,CAAC;IACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC3C;AAED,qDAAqD;AACrD,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,CAAC;IAChC,IAAI,IAAI,IAAI,CAAC;IACb,OAAO,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;CACnC;AAgGD,uFAAuF;AACvF,wBAAsB,KAAK,CAAC,CAAC,EAC3B,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAEzB"}
|
package/dist/watch.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.watch = watch;
|
|
4
|
+
class Watcher {
|
|
5
|
+
readFn;
|
|
6
|
+
onChange;
|
|
7
|
+
everyMs;
|
|
8
|
+
isEqual;
|
|
9
|
+
onError;
|
|
10
|
+
timer;
|
|
11
|
+
currentValue;
|
|
12
|
+
stopped = false;
|
|
13
|
+
inFlight;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.readFn = options.read;
|
|
16
|
+
this.onChange = options.onChange;
|
|
17
|
+
this.everyMs = options.everyMs;
|
|
18
|
+
this.isEqual = options.isEqual ?? defaultIsEqual;
|
|
19
|
+
this.onError = options.onError;
|
|
20
|
+
}
|
|
21
|
+
get current() {
|
|
22
|
+
return this.currentValue;
|
|
23
|
+
}
|
|
24
|
+
async start() {
|
|
25
|
+
await this.refresh();
|
|
26
|
+
if (!this.stopped) {
|
|
27
|
+
this.timer = setInterval(() => {
|
|
28
|
+
void this.refresh();
|
|
29
|
+
}, this.everyMs);
|
|
30
|
+
this.timer.unref();
|
|
31
|
+
}
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
stop() {
|
|
35
|
+
this.stopped = true;
|
|
36
|
+
if (this.timer) {
|
|
37
|
+
clearInterval(this.timer);
|
|
38
|
+
this.timer = undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
refresh() {
|
|
42
|
+
if (this.stopped) {
|
|
43
|
+
return Promise.resolve(this.currentValue);
|
|
44
|
+
}
|
|
45
|
+
if (this.inFlight) {
|
|
46
|
+
return this.inFlight;
|
|
47
|
+
}
|
|
48
|
+
this.inFlight = this.readCurrentValue().finally(() => {
|
|
49
|
+
this.inFlight = undefined;
|
|
50
|
+
});
|
|
51
|
+
return this.inFlight;
|
|
52
|
+
}
|
|
53
|
+
async readCurrentValue() {
|
|
54
|
+
try {
|
|
55
|
+
const current = await this.readFn();
|
|
56
|
+
if (this.stopped) {
|
|
57
|
+
return this.currentValue;
|
|
58
|
+
}
|
|
59
|
+
if (!this.isEqual(current, this.currentValue)) {
|
|
60
|
+
const previous = this.currentValue;
|
|
61
|
+
this.onChange(current, previous);
|
|
62
|
+
this.currentValue = current;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
this.handleError(error);
|
|
67
|
+
}
|
|
68
|
+
return this.currentValue;
|
|
69
|
+
}
|
|
70
|
+
handleError(error) {
|
|
71
|
+
const normalizedError = normalizeError(error);
|
|
72
|
+
if (this.onError) {
|
|
73
|
+
this.onError(normalizedError);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
console.error("watch() read failed:", normalizedError);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Starts watching immediately and resolves after the first read attempt completes. */
|
|
80
|
+
async function watch(options) {
|
|
81
|
+
return new Watcher(options).start();
|
|
82
|
+
}
|
|
83
|
+
function normalizeError(error) {
|
|
84
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
85
|
+
}
|
|
86
|
+
function defaultIsEqual(a, b) {
|
|
87
|
+
if (Object.is(a, b)) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
if (isPrimitive(a) || isPrimitive(b) || b === undefined) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
if (isPlainObjectOrArray(a) && isPlainObjectOrArray(b)) {
|
|
94
|
+
return deepEqual(a, b);
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function isPrimitive(value) {
|
|
104
|
+
return (value === null || (typeof value !== "object" && typeof value !== "function"));
|
|
105
|
+
}
|
|
106
|
+
function isPlainObjectOrArray(value) {
|
|
107
|
+
if (Array.isArray(value)) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
if (value === null || typeof value !== "object") {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
const prototype = Object.getPrototypeOf(value);
|
|
114
|
+
return prototype === Object.prototype || prototype === null;
|
|
115
|
+
}
|
|
116
|
+
function deepEqual(a, b) {
|
|
117
|
+
if (Object.is(a, b)) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
121
|
+
if (a.length !== b.length) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
return a.every((item, index) => deepEqual(item, b[index]));
|
|
125
|
+
}
|
|
126
|
+
if (!isPlainObjectOrArray(a) || !isPlainObjectOrArray(b)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
const aEntries = Object.entries(a);
|
|
130
|
+
const bEntries = Object.entries(b);
|
|
131
|
+
if (aEntries.length !== bEntries.length) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
return aEntries.every(([key, value]) => {
|
|
135
|
+
if (!(key in b)) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
return deepEqual(value, b[key]);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hardlydifficult/poller",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.26",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"clean": "node --eval \"fs.rmSync('dist', { recursive: true, force: true })\""
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@types/node": "25.3.
|
|
18
|
+
"@types/node": "25.3.5",
|
|
19
19
|
"typescript": "5.9.3",
|
|
20
20
|
"vitest": "4.0.18",
|
|
21
21
|
"@vitest/coverage-v8": "4.0.18"
|
package/dist/Poller.d.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/** Generic polling utility that periodically fetches data and invokes a callback when the result changes. */
|
|
2
|
-
export interface PollerOptions<T> {
|
|
3
|
-
fetch: () => Promise<T>;
|
|
4
|
-
onChange: (current: T, previous: T | undefined) => void;
|
|
5
|
-
intervalMs: number;
|
|
6
|
-
onError?: (error: unknown) => void;
|
|
7
|
-
debounceMs?: number;
|
|
8
|
-
comparator?: (current: T, previous: T | undefined) => boolean;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
*/
|
|
13
|
-
export declare class Poller<T> {
|
|
14
|
-
private readonly fetchFn;
|
|
15
|
-
private readonly onChange;
|
|
16
|
-
private readonly intervalMs;
|
|
17
|
-
private readonly onError?;
|
|
18
|
-
private readonly debounceMs;
|
|
19
|
-
private readonly comparator;
|
|
20
|
-
private timer;
|
|
21
|
-
private previous;
|
|
22
|
-
private running;
|
|
23
|
-
private fetching;
|
|
24
|
-
private triggerTimeout;
|
|
25
|
-
constructor(options: PollerOptions<T>);
|
|
26
|
-
/** @deprecated Use `Poller.create(options)` or `new Poller({ ...options })` instead. */
|
|
27
|
-
constructor(fetchFn: () => Promise<T>, onChange: (current: T, previous: T | undefined) => void, intervalMs: number, onError?: (error: unknown) => void);
|
|
28
|
-
static create<T>(options: PollerOptions<T>): Poller<T>;
|
|
29
|
-
start(): Promise<void>;
|
|
30
|
-
stop(): void;
|
|
31
|
-
trigger(debounceMs?: number): void;
|
|
32
|
-
private poll;
|
|
33
|
-
private static resolveOptions;
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=Poller.d.ts.map
|
package/dist/Poller.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Poller.d.ts","sourceRoot":"","sources":["../src/Poller.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,KAAK,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;IACxB,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,CAAC;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,OAAO,CAAC;CAC/D;AAED;;GAEG;AACH,qBAAa,MAAM,CAAC,CAAC;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgD;IACzE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAA2B;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmD;IAE9E,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAA4C;gBAEtD,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;IACrC,wFAAwF;gBAEtF,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,EACvD,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;IAuBpC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAIhD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B,IAAI,IAAI,IAAI;IAYZ,OAAO,CAAC,UAAU,SAAkB,GAAG,IAAI;YAc7B,IAAI;IAqBlB,OAAO,CAAC,MAAM,CAAC,cAAc;CAuB9B"}
|
package/dist/Poller.js
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Poller = void 0;
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
class Poller {
|
|
8
|
-
fetchFn;
|
|
9
|
-
onChange;
|
|
10
|
-
intervalMs;
|
|
11
|
-
onError;
|
|
12
|
-
debounceMs;
|
|
13
|
-
comparator;
|
|
14
|
-
timer;
|
|
15
|
-
previous;
|
|
16
|
-
running = false;
|
|
17
|
-
fetching = false;
|
|
18
|
-
triggerTimeout;
|
|
19
|
-
constructor(optionsOrFetch, onChange, intervalMs, onError) {
|
|
20
|
-
const options = Poller.resolveOptions(optionsOrFetch, onChange, intervalMs, onError);
|
|
21
|
-
this.fetchFn = options.fetch;
|
|
22
|
-
this.onChange = options.onChange;
|
|
23
|
-
this.intervalMs = options.intervalMs;
|
|
24
|
-
this.onError = options.onError;
|
|
25
|
-
this.debounceMs = options.debounceMs ?? 1_000;
|
|
26
|
-
this.comparator = options.comparator ?? defaultIsEqual;
|
|
27
|
-
}
|
|
28
|
-
static create(options) {
|
|
29
|
-
return new Poller(options);
|
|
30
|
-
}
|
|
31
|
-
async start() {
|
|
32
|
-
if (this.running) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
this.running = true;
|
|
36
|
-
await this.poll();
|
|
37
|
-
this.timer = setInterval(() => {
|
|
38
|
-
void this.poll();
|
|
39
|
-
}, this.intervalMs);
|
|
40
|
-
this.timer.unref();
|
|
41
|
-
}
|
|
42
|
-
stop() {
|
|
43
|
-
this.running = false;
|
|
44
|
-
if (this.timer) {
|
|
45
|
-
clearInterval(this.timer);
|
|
46
|
-
this.timer = undefined;
|
|
47
|
-
}
|
|
48
|
-
if (this.triggerTimeout) {
|
|
49
|
-
clearTimeout(this.triggerTimeout);
|
|
50
|
-
this.triggerTimeout = undefined;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
trigger(debounceMs = this.debounceMs) {
|
|
54
|
-
if (!this.running) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
if (this.triggerTimeout) {
|
|
58
|
-
clearTimeout(this.triggerTimeout);
|
|
59
|
-
}
|
|
60
|
-
this.triggerTimeout = setTimeout(() => {
|
|
61
|
-
this.triggerTimeout = undefined;
|
|
62
|
-
void this.poll();
|
|
63
|
-
}, debounceMs);
|
|
64
|
-
this.triggerTimeout.unref();
|
|
65
|
-
}
|
|
66
|
-
async poll() {
|
|
67
|
-
if (this.fetching) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
this.fetching = true;
|
|
71
|
-
try {
|
|
72
|
-
const current = await this.fetchFn();
|
|
73
|
-
if (!this.comparator(current, this.previous)) {
|
|
74
|
-
this.onChange(current, this.previous);
|
|
75
|
-
this.previous = current;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
catch (error) {
|
|
79
|
-
if (this.onError) {
|
|
80
|
-
this.onError(error);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
finally {
|
|
84
|
-
this.fetching = false;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
static resolveOptions(optionsOrFetch, onChange, intervalMs, onError) {
|
|
88
|
-
if (typeof optionsOrFetch !== "function") {
|
|
89
|
-
return optionsOrFetch;
|
|
90
|
-
}
|
|
91
|
-
if (!onChange || intervalMs === undefined) {
|
|
92
|
-
throw new Error("Poller positional constructor requires fetch, onChange, and intervalMs.");
|
|
93
|
-
}
|
|
94
|
-
return {
|
|
95
|
-
fetch: optionsOrFetch,
|
|
96
|
-
onChange,
|
|
97
|
-
intervalMs,
|
|
98
|
-
onError,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
exports.Poller = Poller;
|
|
103
|
-
function defaultIsEqual(a, b) {
|
|
104
|
-
if (Object.is(a, b)) {
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
if (isPrimitive(a) || isPrimitive(b) || b === undefined) {
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
if (isPlainObjectOrArray(a) && isPlainObjectOrArray(b)) {
|
|
111
|
-
return deepEqual(a, b);
|
|
112
|
-
}
|
|
113
|
-
try {
|
|
114
|
-
return JSON.stringify(a) === JSON.stringify(b);
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function isPrimitive(value) {
|
|
121
|
-
return (value === null || (typeof value !== "object" && typeof value !== "function"));
|
|
122
|
-
}
|
|
123
|
-
function isPlainObjectOrArray(value) {
|
|
124
|
-
if (Array.isArray(value)) {
|
|
125
|
-
return true;
|
|
126
|
-
}
|
|
127
|
-
if (value === null || typeof value !== "object") {
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
const prototype = Object.getPrototypeOf(value);
|
|
131
|
-
return prototype === Object.prototype || prototype === null;
|
|
132
|
-
}
|
|
133
|
-
function deepEqual(a, b) {
|
|
134
|
-
if (Object.is(a, b)) {
|
|
135
|
-
return true;
|
|
136
|
-
}
|
|
137
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
138
|
-
if (a.length !== b.length) {
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
return a.every((item, index) => deepEqual(item, b[index]));
|
|
142
|
-
}
|
|
143
|
-
if (!isPlainObjectOrArray(a) || !isPlainObjectOrArray(b)) {
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
const aEntries = Object.entries(a);
|
|
147
|
-
const bEntries = Object.entries(b);
|
|
148
|
-
if (aEntries.length !== bEntries.length) {
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
return aEntries.every(([key, value]) => {
|
|
152
|
-
if (!(key in b)) {
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
return deepEqual(value, b[key]);
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
//# sourceMappingURL=Poller.js.map
|
package/dist/Poller.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Poller.js","sourceRoot":"","sources":["../src/Poller.ts"],"names":[],"mappings":"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"}
|