@marianmeres/fetch-store 3.1.0 → 3.1.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/README.md +3 -1
- package/dist/fetch-stream-store.d.ts +2 -2
- package/dist/fetch-stream-store.js +28 -15
- package/dist/types.d.ts +2 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -99,10 +99,12 @@ const feed = createFetchStreamStore<Message>((emit, url: string) => {
|
|
|
99
99
|
const es = new EventSource(url);
|
|
100
100
|
es.onmessage = (e) => emit("data", JSON.parse(e.data));
|
|
101
101
|
es.onerror = (e) => emit("error", e);
|
|
102
|
-
return () =>
|
|
102
|
+
return () => es.close();
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
const stop = feed.fetchStream(["/api/events"]);
|
|
106
|
+
// ...later: closes the connection, sets isFetching: false
|
|
107
|
+
stop();
|
|
106
108
|
```
|
|
107
109
|
|
|
108
110
|
## Features
|
|
@@ -19,11 +19,11 @@ import type { FetchStreamEventName, FetchStreamStore, FetchStreamStoreOptions }
|
|
|
19
19
|
* const eventSource = new EventSource(url);
|
|
20
20
|
* eventSource.onmessage = (e) => emit("data", JSON.parse(e.data));
|
|
21
21
|
* eventSource.onerror = (e) => emit("error", e);
|
|
22
|
-
* return () =>
|
|
22
|
+
* return () => eventSource.close();
|
|
23
23
|
* });
|
|
24
24
|
*
|
|
25
25
|
* const stop = sseStore.fetchStream(["/api/events"]);
|
|
26
|
-
* // Later: stop()
|
|
26
|
+
* // Later: stop() closes the connection and the run (isFetching: false, lastFetchEnd)
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
29
|
export declare const createFetchStreamStore: <T, A extends unknown[] = unknown[]>(fetchStreamWorker: (emit: (eventName: FetchStreamEventName, eventData?: T | Error) => void, ...args: A) => (() => void) | void, initial?: T | null, options?: Partial<FetchStreamStoreOptions<T>>) => FetchStreamStore<T, A>;
|
|
@@ -19,11 +19,11 @@ const DEFAULT_OPTIONS = {};
|
|
|
19
19
|
* const eventSource = new EventSource(url);
|
|
20
20
|
* eventSource.onmessage = (e) => emit("data", JSON.parse(e.data));
|
|
21
21
|
* eventSource.onerror = (e) => emit("error", e);
|
|
22
|
-
* return () =>
|
|
22
|
+
* return () => eventSource.close();
|
|
23
23
|
* });
|
|
24
24
|
*
|
|
25
25
|
* const stop = sseStore.fetchStream(["/api/events"]);
|
|
26
|
-
* // Later: stop()
|
|
26
|
+
* // Later: stop() closes the connection and the run (isFetching: false, lastFetchEnd)
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
29
|
export const createFetchStreamStore = (fetchStreamWorker, initial = null, options = {}) => {
|
|
@@ -40,13 +40,17 @@ export const createFetchStreamStore = (fetchStreamWorker, initial = null, option
|
|
|
40
40
|
const _dataStore = createStore(initial);
|
|
41
41
|
const _metaStore = createStore(_createMetaObj());
|
|
42
42
|
const { subscribe, get } = createDerivedStore([_dataStore, _metaStore], ([data, meta]) => ({ data, ...meta }));
|
|
43
|
-
// Tracks the
|
|
44
|
-
|
|
43
|
+
// Tracks the stop fn of the currently running stream so reset() and a new
|
|
44
|
+
// fetchStream() can stop it.
|
|
45
|
+
let _currentStop = null;
|
|
45
46
|
const fetchStream = (fetchArgs = [], recursiveDelayMs = 0) => {
|
|
46
47
|
let _timer;
|
|
47
48
|
let _aborted = false;
|
|
48
49
|
let _abortFn;
|
|
49
|
-
|
|
50
|
+
// `closeRun` is false when the caller is about to overwrite meta anyway
|
|
51
|
+
// (reset, or a new fetchStream superseding this one), so subscribers see no
|
|
52
|
+
// intermediate `isFetching: false` flicker.
|
|
53
|
+
const stop = (closeRun) => {
|
|
50
54
|
if (_aborted)
|
|
51
55
|
return;
|
|
52
56
|
_aborted = true;
|
|
@@ -60,9 +64,18 @@ export const createFetchStreamStore = (fetchStreamWorker, initial = null, option
|
|
|
60
64
|
// cleanup should not throw, but guard anyway
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
|
-
if (
|
|
64
|
-
|
|
67
|
+
if (_currentStop === stop)
|
|
68
|
+
_currentStop = null;
|
|
69
|
+
// Every emit from here on is ignored (including an "end" from the cleanup
|
|
70
|
+
// above), so the store closes the run itself. Nothing to close when idle
|
|
71
|
+
// between recursive runs.
|
|
72
|
+
const meta = _metaStore.get();
|
|
73
|
+
if (closeRun && meta.isFetching) {
|
|
74
|
+
_metaStore.set({ ...meta, isFetching: false, lastFetchEnd: new Date() });
|
|
75
|
+
}
|
|
65
76
|
};
|
|
77
|
+
// Public cancel fn takes no args (safe to pass directly as an event handler).
|
|
78
|
+
const cancel = () => stop(true);
|
|
66
79
|
const normalizedArgs = (Array.isArray(fetchArgs) ? fetchArgs : [fetchArgs]);
|
|
67
80
|
const runOnce = () => {
|
|
68
81
|
if (_aborted)
|
|
@@ -131,19 +144,19 @@ export const createFetchStreamStore = (fetchStreamWorker, initial = null, option
|
|
|
131
144
|
});
|
|
132
145
|
}
|
|
133
146
|
};
|
|
134
|
-
// If a previous stream was still running,
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
147
|
+
// If a previous stream was still running, stop it before starting a new one.
|
|
148
|
+
if (_currentStop)
|
|
149
|
+
_currentStop(false);
|
|
150
|
+
_currentStop = stop;
|
|
138
151
|
runOnce();
|
|
139
152
|
return cancel;
|
|
140
153
|
};
|
|
141
154
|
const reset = () => {
|
|
142
155
|
// Stop any running stream (calls the worker's cleanup function).
|
|
143
|
-
if (
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
156
|
+
if (_currentStop) {
|
|
157
|
+
const s = _currentStop;
|
|
158
|
+
_currentStop = null;
|
|
159
|
+
s(false);
|
|
147
160
|
}
|
|
148
161
|
_dataStore.set(initial);
|
|
149
162
|
_metaStore.set(_createMetaObj());
|
package/dist/types.d.ts
CHANGED
|
@@ -171,7 +171,8 @@ export interface FetchStreamStore<T, A extends unknown[] = unknown[]> extends St
|
|
|
171
171
|
* Starts the stream and optionally restarts it after completion.
|
|
172
172
|
* @param args - Arguments passed to the stream worker
|
|
173
173
|
* @param recursiveDelayMs - Delay before restarting stream after "end" event (0 = no restart)
|
|
174
|
-
* @returns Cancel function
|
|
174
|
+
* @returns Cancel function: calls the worker's cleanup, ignores any later emits,
|
|
175
|
+
* and closes the run (`isFetching: false`, `lastFetchEnd`) if it was still active.
|
|
175
176
|
*/
|
|
176
177
|
fetchStream: (args?: A | unknown, recursiveDelayMs?: number | (() => number)) => () => void;
|
|
177
178
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marianmeres/fetch-store",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/mod.js",
|
|
6
6
|
"types": "dist/mod.d.ts",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"url": "https://github.com/marianmeres/fetch-store/issues"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@marianmeres/pubsub": "^3.
|
|
18
|
-
"@marianmeres/store": "^3.0.
|
|
17
|
+
"@marianmeres/pubsub": "^3.1.0",
|
|
18
|
+
"@marianmeres/store": "^3.0.1"
|
|
19
19
|
}
|
|
20
20
|
}
|