@tanstack/pacer 0.18.0 → 0.20.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.md +8 -8
- package/dist/async-batcher.cjs +1 -0
- package/dist/async-batcher.cjs.map +1 -1
- package/dist/async-batcher.js.map +1 -1
- package/dist/async-debouncer.cjs +1 -0
- package/dist/async-debouncer.cjs.map +1 -1
- package/dist/async-debouncer.js.map +1 -1
- package/dist/async-queuer.cjs +1 -0
- package/dist/async-queuer.cjs.map +1 -1
- package/dist/async-queuer.js.map +1 -1
- package/dist/async-rate-limiter.cjs +1 -0
- package/dist/async-rate-limiter.cjs.map +1 -1
- package/dist/async-rate-limiter.js.map +1 -1
- package/dist/async-retryer.cjs +1 -0
- package/dist/async-retryer.cjs.map +1 -1
- package/dist/async-retryer.js.map +1 -1
- package/dist/async-throttler.cjs +1 -0
- package/dist/async-throttler.cjs.map +1 -1
- package/dist/async-throttler.js.map +1 -1
- package/dist/batcher.cjs +1 -0
- package/dist/batcher.cjs.map +1 -1
- package/dist/batcher.js.map +1 -1
- package/dist/debouncer.cjs +1 -0
- package/dist/debouncer.cjs.map +1 -1
- package/dist/debouncer.js.map +1 -1
- package/dist/event-client.cjs +39 -3
- package/dist/event-client.cjs.map +1 -1
- package/dist/event-client.d.cts +53 -36
- package/dist/event-client.d.ts +53 -36
- package/dist/event-client.js +37 -4
- package/dist/event-client.js.map +1 -1
- package/dist/index.cjs +3 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/queuer.cjs +1 -0
- package/dist/queuer.cjs.map +1 -1
- package/dist/queuer.js.map +1 -1
- package/dist/rate-limiter.cjs +1 -0
- package/dist/rate-limiter.cjs.map +1 -1
- package/dist/rate-limiter.js.map +1 -1
- package/dist/throttler.cjs +1 -0
- package/dist/throttler.cjs.map +1 -1
- package/dist/throttler.js.map +1 -1
- package/dist/utils.cjs +1 -0
- package/dist/utils.cjs.map +1 -1
- package/package.json +33 -33
- package/src/async-batcher.ts +6 -2
- package/src/async-debouncer.ts +6 -2
- package/src/async-queuer.ts +6 -2
- package/src/async-rate-limiter.ts +6 -2
- package/src/async-retryer.ts +6 -2
- package/src/async-throttler.ts +6 -2
- package/src/batcher.ts +6 -2
- package/src/debouncer.ts +4 -2
- package/src/event-client.ts +109 -48
- package/src/index.ts +10 -2
- package/src/queuer.ts +4 -2
- package/src/rate-limiter.ts +4 -2
- package/src/throttler.ts +5 -3
package/src/event-client.ts
CHANGED
|
@@ -1,68 +1,129 @@
|
|
|
1
1
|
import { EventClient } from '@tanstack/devtools-event-client'
|
|
2
|
-
import type { AsyncBatcher } from './async-batcher'
|
|
3
|
-
import type { AsyncDebouncer } from './async-debouncer'
|
|
4
|
-
import type { AsyncQueuer } from './async-queuer'
|
|
5
|
-
import type { AsyncRateLimiter } from './async-rate-limiter'
|
|
6
|
-
import type { AsyncRetryer } from './async-retryer'
|
|
7
|
-
import type { AsyncThrottler } from './async-throttler'
|
|
8
|
-
import type { Debouncer } from './debouncer'
|
|
9
|
-
import type { Batcher } from './batcher'
|
|
10
|
-
import type { Queuer } from './queuer'
|
|
11
|
-
import type { RateLimiter } from './rate-limiter'
|
|
12
|
-
import type { Throttler } from './throttler'
|
|
13
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Payload on the devtools event bus must be JSON-serializable: `ClientEventBus`
|
|
5
|
+
* always stringifies events for `emitToServer` and `BroadcastChannel`, so live
|
|
6
|
+
* util instances (with reactive `store` graphs) cannot be sent as-is.
|
|
7
|
+
*
|
|
8
|
+
* Live instances are kept in {@link pacerDevtoolsInstancesByKey} for the panel.
|
|
9
|
+
*/
|
|
10
|
+
export interface PacerDevtoolsWirePayload {
|
|
11
|
+
key: string
|
|
12
|
+
store: { state: unknown }
|
|
13
|
+
options: unknown
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const pacerDevtoolsInstancesByKey = new Map<string, unknown>()
|
|
17
|
+
|
|
18
|
+
export function registerPacerDevtoolsInstance(
|
|
19
|
+
key: string,
|
|
20
|
+
instance: unknown,
|
|
21
|
+
): void {
|
|
22
|
+
pacerDevtoolsInstancesByKey.set(key, instance)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getPacerDevtoolsInstance(key: string): unknown {
|
|
26
|
+
return pacerDevtoolsInstancesByKey.get(key)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function cloneJsonSafe(value: unknown): unknown {
|
|
30
|
+
if (value === undefined) {
|
|
31
|
+
return undefined
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(JSON.stringify(value)) as unknown
|
|
35
|
+
} catch {
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function readStoreSnapshot(store: {
|
|
41
|
+
get?: () => unknown
|
|
42
|
+
state?: unknown
|
|
43
|
+
}): unknown {
|
|
44
|
+
if (typeof store.get === 'function') {
|
|
45
|
+
return store.get()
|
|
46
|
+
}
|
|
47
|
+
return store.state
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function toPacerDevtoolsWirePayload(instance: {
|
|
51
|
+
key: string
|
|
52
|
+
store: { get?: () => unknown; state?: unknown }
|
|
53
|
+
options: unknown
|
|
54
|
+
}): PacerDevtoolsWirePayload {
|
|
55
|
+
return {
|
|
56
|
+
key: instance.key,
|
|
57
|
+
store: { state: cloneJsonSafe(readStoreSnapshot(instance.store)) },
|
|
58
|
+
options: cloneJsonSafe(instance.options),
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Suffix-only keys: {@link EventClient} prepends `pluginId:` (`pacer:`) at runtime
|
|
64
|
+
* for `emit` / `on`. Wire `type` values are `pacer:${key}`.
|
|
65
|
+
*/
|
|
14
66
|
export interface PacerEventMap {
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
67
|
+
'd-AsyncBatcher': PacerDevtoolsWirePayload
|
|
68
|
+
'd-AsyncDebouncer': PacerDevtoolsWirePayload
|
|
69
|
+
'd-AsyncQueuer': PacerDevtoolsWirePayload
|
|
70
|
+
'd-AsyncRateLimiter': PacerDevtoolsWirePayload
|
|
71
|
+
'd-AsyncRetryer': PacerDevtoolsWirePayload
|
|
72
|
+
'd-AsyncThrottler': PacerDevtoolsWirePayload
|
|
73
|
+
'd-Batcher': PacerDevtoolsWirePayload
|
|
74
|
+
'd-Debouncer': PacerDevtoolsWirePayload
|
|
75
|
+
'd-Queuer': PacerDevtoolsWirePayload
|
|
76
|
+
'd-RateLimiter': PacerDevtoolsWirePayload
|
|
77
|
+
'd-Throttler': PacerDevtoolsWirePayload
|
|
78
|
+
AsyncBatcher: PacerDevtoolsWirePayload
|
|
79
|
+
AsyncDebouncer: PacerDevtoolsWirePayload
|
|
80
|
+
AsyncQueuer: PacerDevtoolsWirePayload
|
|
81
|
+
AsyncRateLimiter: PacerDevtoolsWirePayload
|
|
82
|
+
AsyncRetryer: PacerDevtoolsWirePayload
|
|
83
|
+
AsyncThrottler: PacerDevtoolsWirePayload
|
|
84
|
+
Batcher: PacerDevtoolsWirePayload
|
|
85
|
+
Debouncer: PacerDevtoolsWirePayload
|
|
86
|
+
Queuer: PacerDevtoolsWirePayload
|
|
87
|
+
RateLimiter: PacerDevtoolsWirePayload
|
|
88
|
+
Throttler: PacerDevtoolsWirePayload
|
|
37
89
|
}
|
|
38
90
|
|
|
39
|
-
export type PacerEventName = keyof PacerEventMap
|
|
40
|
-
|
|
41
|
-
|
|
91
|
+
export type PacerEventName = keyof PacerEventMap
|
|
92
|
+
|
|
93
|
+
type PacerUtilEmitSource = {
|
|
94
|
+
key?: string
|
|
95
|
+
store: { get?: () => unknown; state?: unknown }
|
|
96
|
+
options: unknown
|
|
97
|
+
}
|
|
42
98
|
|
|
43
99
|
class PacerEventClient extends EventClient<PacerEventMap> {
|
|
44
100
|
constructor(props?: { debug: boolean }) {
|
|
45
101
|
super({
|
|
46
102
|
pluginId: 'pacer',
|
|
47
103
|
debug: props?.debug,
|
|
104
|
+
/**
|
|
105
|
+
* TanStack Devtools starts `ClientEventBus` inside an async dynamic import
|
|
106
|
+
* after the first commit. Pacer utils often emit during the first render
|
|
107
|
+
* (constructor → store sync). `EventClient` only retries `tanstack-connect`
|
|
108
|
+
* `#maxRetries` times at `reconnectEveryMs` before it gives up and drops
|
|
109
|
+
* all queued events permanently. Default 300ms × 5 ≈ 1.5s is often too
|
|
110
|
+
* short; Form uses 1000ms here for the same reason.
|
|
111
|
+
*/
|
|
112
|
+
reconnectEveryMs: 1000,
|
|
48
113
|
})
|
|
49
114
|
}
|
|
50
115
|
}
|
|
51
116
|
|
|
52
|
-
export const emitChange = <
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
`${string}:${string}`
|
|
56
|
-
> extends `${string}:${infer S}`
|
|
57
|
-
? S
|
|
58
|
-
: never,
|
|
59
|
-
>(
|
|
60
|
-
event: TSuffix,
|
|
61
|
-
payload: PacerEventMap[`pacer:${TSuffix}`],
|
|
117
|
+
export const emitChange = <TEvent extends keyof PacerEventMap>(
|
|
118
|
+
event: TEvent,
|
|
119
|
+
instance: PacerUtilEmitSource,
|
|
62
120
|
) => {
|
|
63
|
-
|
|
64
|
-
|
|
121
|
+
const key = instance.key
|
|
122
|
+
if (!key) {
|
|
123
|
+
return
|
|
65
124
|
}
|
|
125
|
+
registerPacerDevtoolsInstance(key, instance)
|
|
126
|
+
pacerEventClient.emit(event, toPacerDevtoolsWirePayload({ ...instance, key }))
|
|
66
127
|
}
|
|
67
128
|
|
|
68
129
|
export const pacerEventClient = new PacerEventClient()
|
package/src/index.ts
CHANGED
|
@@ -12,5 +12,13 @@ export * from './throttler'
|
|
|
12
12
|
export * from './types'
|
|
13
13
|
export * from './utils'
|
|
14
14
|
|
|
15
|
-
export {
|
|
16
|
-
|
|
15
|
+
export {
|
|
16
|
+
emitChange,
|
|
17
|
+
getPacerDevtoolsInstance,
|
|
18
|
+
pacerEventClient,
|
|
19
|
+
} from './event-client'
|
|
20
|
+
export type {
|
|
21
|
+
PacerDevtoolsWirePayload,
|
|
22
|
+
PacerEventMap,
|
|
23
|
+
PacerEventName,
|
|
24
|
+
} from './event-client'
|
package/src/queuer.ts
CHANGED
|
@@ -305,8 +305,10 @@ export class Queuer<TValue> {
|
|
|
305
305
|
if (this.key) {
|
|
306
306
|
pacerEventClient.on('d-Queuer', (event) => {
|
|
307
307
|
if (event.payload.key !== this.key) return
|
|
308
|
-
this.#setState(
|
|
309
|
-
|
|
308
|
+
this.#setState(
|
|
309
|
+
event.payload.store.state as Partial<QueuerState<TValue>>,
|
|
310
|
+
)
|
|
311
|
+
this.setOptions(event.payload.options as Partial<QueuerOptions<TValue>>)
|
|
310
312
|
})
|
|
311
313
|
}
|
|
312
314
|
}
|
package/src/rate-limiter.ts
CHANGED
|
@@ -177,8 +177,10 @@ export class RateLimiter<TFn extends AnyFunction> {
|
|
|
177
177
|
if (this.key) {
|
|
178
178
|
pacerEventClient.on('d-RateLimiter', (event) => {
|
|
179
179
|
if (event.payload.key !== this.key) return
|
|
180
|
-
this.#setState(event.payload.store.state)
|
|
181
|
-
this.setOptions(
|
|
180
|
+
this.#setState(event.payload.store.state as Partial<RateLimiterState>)
|
|
181
|
+
this.setOptions(
|
|
182
|
+
event.payload.options as Partial<RateLimiterOptions<TFn>>,
|
|
183
|
+
)
|
|
182
184
|
})
|
|
183
185
|
}
|
|
184
186
|
}
|
package/src/throttler.ts
CHANGED
|
@@ -149,7 +149,7 @@ const defaultOptions: Omit<
|
|
|
149
149
|
*/
|
|
150
150
|
export class Throttler<TFn extends AnyFunction> {
|
|
151
151
|
readonly store: Store<Readonly<ThrottlerState<TFn>>> = new Store(
|
|
152
|
-
getDefaultThrottlerState(),
|
|
152
|
+
getDefaultThrottlerState<TFn>(),
|
|
153
153
|
)
|
|
154
154
|
key: string | undefined
|
|
155
155
|
options: ThrottlerOptions<TFn>
|
|
@@ -169,8 +169,10 @@ export class Throttler<TFn extends AnyFunction> {
|
|
|
169
169
|
if (this.key) {
|
|
170
170
|
pacerEventClient.on('d-Throttler', (event) => {
|
|
171
171
|
if (event.payload.key !== this.key) return
|
|
172
|
-
this.#setState(
|
|
173
|
-
|
|
172
|
+
this.#setState(
|
|
173
|
+
event.payload.store.state as Partial<ThrottlerState<TFn>>,
|
|
174
|
+
)
|
|
175
|
+
this.setOptions(event.payload.options as Partial<ThrottlerOptions<TFn>>)
|
|
174
176
|
})
|
|
175
177
|
}
|
|
176
178
|
}
|