1
1
import Mitt from 'mitt'
2
- import { debug } from './debug'
3
- import { error } from './errors'
4
- import { getQueuedValue } from './update-queue'
5
2
6
3
export const SYNC_EVENT_KEY = Symbol ( '__nuqs__SYNC__' )
7
- export const NOSYNC_MARKER = '__nuqs__NO_SYNC__'
8
4
const NOTIFY_EVENT_KEY = Symbol ( '__nuqs__NOTIFY__' )
9
5
10
6
export type QueryUpdateSource = 'internal' | 'external'
@@ -24,91 +20,3 @@ type EventMap = {
24
20
}
25
21
26
22
export const emitter = Mitt < EventMap > ( )
27
-
28
- declare global {
29
- interface History {
30
- __nuqs_patched ?: string
31
- }
32
- }
33
-
34
- if ( typeof history === 'object' ) {
35
- patchHistory ( )
36
- }
37
-
38
- function patchHistory ( ) {
39
- // This is replaced with the package.json version by scripts/prepack.sh
40
- // after semantic-release has done updating the version number.
41
- const version = '0.0.0-inject-version-here'
42
- const patched = history . __nuqs_patched
43
- if ( patched ) {
44
- if ( patched !== version ) {
45
- console . error ( error ( 409 ) , patched , version )
46
- }
47
- return
48
- }
49
- debug ( '[nuqs] Patching history with %s' , version )
50
- for ( const method of [ 'pushState' , 'replaceState' ] as const ) {
51
- const original = history [ method ] . bind ( history )
52
- history [ method ] = function nuqs_patchedHistory (
53
- state : any ,
54
- title : string ,
55
- url ?: string | URL | null
56
- ) {
57
- if ( ! url ) {
58
- // Null URL is only used for state changes,
59
- // we're not interested in reacting to those.
60
- debug ( '[nuqs] history.%s(null) (%s) %O' , method , title , state )
61
- return original ( state , title , url )
62
- }
63
- const source = title === NOSYNC_MARKER ? 'internal' : 'external'
64
- const search = new URL ( url , location . origin ) . searchParams
65
- debug ( '[nuqs] history.%s(%s) (%s) %O' , method , url , source , state )
66
- // If someone else than our hooks have updated the URL,
67
- // send out a signal for them to sync their internal state.
68
- if ( source === 'external' ) {
69
- for ( const [ key , value ] of search . entries ( ) ) {
70
- const queueValue = getQueuedValue ( key )
71
- if ( queueValue !== null && queueValue !== value ) {
72
- debug (
73
- '[nuqs] Overwrite detected for key: %s, Server: %s, queue: %s' ,
74
- key ,
75
- value ,
76
- queueValue
77
- )
78
- search . set ( key , queueValue )
79
- }
80
- }
81
- // Here we're delaying application to next tick to avoid:
82
- // `Warning: useInsertionEffect must not schedule updates.`
83
- //
84
- // Because the emitter runs in sync, this would trigger
85
- // each hook's setInternalState updates, so we schedule
86
- // those after the current batch of events.
87
- // Because we don't know if the history method would
88
- // have been applied by then, we're also sending the
89
- // parsed query string to the hooks so they don't need
90
- // to rely on the URL being up to date.
91
- setTimeout ( ( ) => {
92
- debug (
93
- '[nuqs] External history.%s call: triggering sync with %s' ,
94
- method ,
95
- search
96
- )
97
- emitter . emit ( SYNC_EVENT_KEY , search )
98
- emitter . emit ( NOTIFY_EVENT_KEY , { search, source } )
99
- } , 0 )
100
- } else {
101
- setTimeout ( ( ) => {
102
- emitter . emit ( NOTIFY_EVENT_KEY , { search, source } )
103
- } , 0 )
104
- }
105
- return original ( state , title === NOSYNC_MARKER ? '' : title , url )
106
- }
107
- }
108
- Object . defineProperty ( history , '__nuqs_patched' , {
109
- value : version ,
110
- writable : false ,
111
- enumerable : false ,
112
- configurable : false
113
- } )
114
- }
0 commit comments