@sanity/sdk 0.0.0-chore-react-18-compat.1 → 0.0.0-chore-react-18-compat.3

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.
Files changed (134) hide show
  1. package/dist/index.d.ts +441 -322
  2. package/dist/index.js +1685 -1481
  3. package/dist/index.js.map +1 -1
  4. package/package.json +13 -15
  5. package/src/_exports/index.ts +32 -30
  6. package/src/auth/authStore.test.ts +149 -104
  7. package/src/auth/authStore.ts +51 -100
  8. package/src/auth/handleAuthCallback.test.ts +67 -34
  9. package/src/auth/handleAuthCallback.ts +8 -7
  10. package/src/auth/logout.test.ts +61 -29
  11. package/src/auth/logout.ts +26 -28
  12. package/src/auth/refreshStampedToken.test.ts +197 -91
  13. package/src/auth/refreshStampedToken.ts +170 -59
  14. package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +5 -5
  15. package/src/auth/subscribeToStateAndFetchCurrentUser.ts +45 -47
  16. package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +4 -5
  17. package/src/auth/subscribeToStorageEventsAndSetToken.ts +22 -24
  18. package/src/client/clientStore.test.ts +131 -67
  19. package/src/client/clientStore.ts +117 -116
  20. package/src/comlink/controller/actions/destroyController.test.ts +38 -13
  21. package/src/comlink/controller/actions/destroyController.ts +11 -15
  22. package/src/comlink/controller/actions/getOrCreateChannel.test.ts +56 -27
  23. package/src/comlink/controller/actions/getOrCreateChannel.ts +37 -35
  24. package/src/comlink/controller/actions/getOrCreateController.test.ts +27 -16
  25. package/src/comlink/controller/actions/getOrCreateController.ts +23 -22
  26. package/src/comlink/controller/actions/releaseChannel.test.ts +37 -13
  27. package/src/comlink/controller/actions/releaseChannel.ts +22 -21
  28. package/src/comlink/controller/comlinkControllerStore.test.ts +65 -36
  29. package/src/comlink/controller/comlinkControllerStore.ts +44 -5
  30. package/src/comlink/node/actions/getOrCreateNode.test.ts +31 -15
  31. package/src/comlink/node/actions/getOrCreateNode.ts +30 -29
  32. package/src/comlink/node/actions/releaseNode.test.ts +75 -55
  33. package/src/comlink/node/actions/releaseNode.ts +19 -21
  34. package/src/comlink/node/comlinkNodeStore.test.ts +6 -11
  35. package/src/comlink/node/comlinkNodeStore.ts +22 -5
  36. package/src/config/authConfig.ts +79 -0
  37. package/src/config/sanityConfig.ts +48 -0
  38. package/src/datasets/datasets.test.ts +2 -2
  39. package/src/datasets/datasets.ts +18 -5
  40. package/src/document/actions.test.ts +22 -10
  41. package/src/document/actions.ts +44 -56
  42. package/src/document/applyDocumentActions.test.ts +96 -36
  43. package/src/document/applyDocumentActions.ts +140 -99
  44. package/src/document/documentStore.test.ts +103 -155
  45. package/src/document/documentStore.ts +247 -238
  46. package/src/document/listen.ts +56 -55
  47. package/src/document/patchOperations.ts +0 -43
  48. package/src/document/permissions.test.ts +25 -12
  49. package/src/document/permissions.ts +11 -4
  50. package/src/document/processActions.test.ts +41 -8
  51. package/src/document/reducers.test.ts +87 -16
  52. package/src/document/reducers.ts +2 -2
  53. package/src/document/sharedListener.test.ts +34 -16
  54. package/src/document/sharedListener.ts +33 -11
  55. package/src/preview/getPreviewState.test.ts +40 -39
  56. package/src/preview/getPreviewState.ts +68 -56
  57. package/src/preview/previewConstants.ts +43 -0
  58. package/src/preview/previewQuery.test.ts +1 -1
  59. package/src/preview/previewQuery.ts +4 -5
  60. package/src/preview/previewStore.test.ts +13 -58
  61. package/src/preview/previewStore.ts +7 -21
  62. package/src/preview/resolvePreview.test.ts +33 -104
  63. package/src/preview/resolvePreview.ts +11 -21
  64. package/src/preview/subscribeToStateAndFetchBatches.test.ts +96 -97
  65. package/src/preview/subscribeToStateAndFetchBatches.ts +85 -81
  66. package/src/preview/util.ts +1 -0
  67. package/src/project/project.test.ts +3 -3
  68. package/src/project/project.ts +28 -5
  69. package/src/projection/getProjectionState.test.ts +188 -72
  70. package/src/projection/getProjectionState.ts +92 -62
  71. package/src/projection/projectionQuery.test.ts +114 -12
  72. package/src/projection/projectionQuery.ts +75 -32
  73. package/src/projection/projectionStore.test.ts +13 -51
  74. package/src/projection/projectionStore.ts +6 -43
  75. package/src/projection/resolveProjection.test.ts +32 -127
  76. package/src/projection/resolveProjection.ts +16 -28
  77. package/src/projection/subscribeToStateAndFetchBatches.test.ts +203 -116
  78. package/src/projection/subscribeToStateAndFetchBatches.ts +140 -85
  79. package/src/projection/types.ts +50 -0
  80. package/src/projection/util.ts +3 -1
  81. package/src/projects/projects.test.ts +13 -4
  82. package/src/projects/projects.ts +6 -1
  83. package/src/query/queryStore.test.ts +10 -47
  84. package/src/query/queryStore.ts +151 -133
  85. package/src/query/queryStoreConstants.ts +2 -0
  86. package/src/store/createActionBinder.test.ts +153 -0
  87. package/src/store/createActionBinder.ts +176 -0
  88. package/src/store/createSanityInstance.test.ts +84 -0
  89. package/src/store/createSanityInstance.ts +124 -0
  90. package/src/store/createStateSourceAction.test.ts +196 -0
  91. package/src/store/createStateSourceAction.ts +260 -0
  92. package/src/store/createStoreInstance.test.ts +81 -0
  93. package/src/store/createStoreInstance.ts +80 -0
  94. package/src/store/createStoreState.test.ts +85 -0
  95. package/src/store/createStoreState.ts +92 -0
  96. package/src/store/defineStore.test.ts +18 -0
  97. package/src/store/defineStore.ts +81 -0
  98. package/src/users/reducers.test.ts +318 -0
  99. package/src/users/reducers.ts +88 -0
  100. package/src/users/types.ts +46 -4
  101. package/src/users/usersConstants.ts +4 -0
  102. package/src/users/usersStore.test.ts +350 -223
  103. package/src/users/usersStore.ts +285 -149
  104. package/src/utils/createFetcherStore.test.ts +6 -7
  105. package/src/utils/createFetcherStore.ts +150 -153
  106. package/src/utils/createGroqSearchFilter.test.ts +75 -0
  107. package/src/utils/createGroqSearchFilter.ts +85 -0
  108. package/src/{common/util.test.ts → utils/hashString.test.ts} +1 -1
  109. package/dist/index.cjs +0 -4888
  110. package/dist/index.cjs.map +0 -1
  111. package/dist/index.d.cts +0 -2121
  112. package/src/auth/fetchLoginUrls.test.ts +0 -163
  113. package/src/auth/fetchLoginUrls.ts +0 -74
  114. package/src/common/createLiveEventSubscriber.test.ts +0 -121
  115. package/src/common/createLiveEventSubscriber.ts +0 -55
  116. package/src/common/types.ts +0 -4
  117. package/src/instance/identity.test.ts +0 -46
  118. package/src/instance/identity.ts +0 -29
  119. package/src/instance/sanityInstance.test.ts +0 -77
  120. package/src/instance/sanityInstance.ts +0 -57
  121. package/src/instance/types.ts +0 -37
  122. package/src/preview/getPreviewProjection.ts +0 -45
  123. package/src/resources/README.md +0 -370
  124. package/src/resources/createAction.test.ts +0 -101
  125. package/src/resources/createAction.ts +0 -44
  126. package/src/resources/createResource.test.ts +0 -112
  127. package/src/resources/createResource.ts +0 -102
  128. package/src/resources/createStateSourceAction.test.ts +0 -114
  129. package/src/resources/createStateSourceAction.ts +0 -83
  130. package/src/resources/createStore.test.ts +0 -67
  131. package/src/resources/createStore.ts +0 -46
  132. package/src/store/createStore.test.ts +0 -108
  133. package/src/store/createStore.ts +0 -106
  134. /package/src/{common/util.ts → utils/hashString.ts} +0 -0
@@ -1,104 +1,159 @@
1
- import {type SanityClient, type SyncTag} from '@sanity/client'
1
+ import {isEqual} from 'lodash-es'
2
2
  import {
3
3
  combineLatest,
4
4
  debounceTime,
5
+ defer,
5
6
  distinctUntilChanged,
6
7
  EMPTY,
8
+ filter,
9
+ from,
7
10
  map,
8
11
  Observable,
9
12
  pairwise,
10
13
  startWith,
14
+ Subscription,
11
15
  switchMap,
12
16
  tap,
13
- withLatestFrom,
14
17
  } from 'rxjs'
15
18
 
16
- import {getClientState} from '../client/clientStore'
17
- import {type ActionContext, createInternalAction} from '../resources/createAction'
18
- import {createProjectionQuery, processProjectionQuery} from './projectionQuery'
19
- import {type ProjectionQueryResult, type ProjectionStoreState} from './projectionStore'
20
- import {PROJECTION_TAG} from './util'
19
+ import {getQueryState, resolveQuery} from '../query/queryStore'
20
+ import {type StoreContext} from '../store/defineStore'
21
+ import {
22
+ createProjectionQuery,
23
+ processProjectionQuery,
24
+ type ProjectionQueryResult,
25
+ } from './projectionQuery'
26
+ import {type ProjectionStoreState} from './types'
27
+ import {PROJECTION_PERSPECTIVE, PROJECTION_TAG} from './util'
21
28
 
22
29
  const BATCH_DEBOUNCE_TIME = 50
23
30
 
24
- export const subscribeToStateAndFetchBatches = createInternalAction(
25
- ({state, instance}: ActionContext<ProjectionStoreState>) => {
26
- return function () {
27
- const client$ = new Observable<SanityClient>((observer) =>
28
- getClientState(instance, {apiVersion: 'vX'}).observable.subscribe(observer),
29
- )
30
-
31
- const documentProjections$ = state.observable.pipe(
32
- map((i) => i.documentProjections),
33
- distinctUntilChanged(),
34
- )
35
- const lastLiveEventId$ = state.observable.pipe(
36
- map((i) => i.lastLiveEventId),
37
- distinctUntilChanged(),
38
- )
39
-
40
- const newSubscriberIds$ = state.observable.pipe(
41
- map(({subscriptions}) => new Set(Object.keys(subscriptions))),
42
- distinctUntilChanged((a, b) =>
43
- a.size !== b.size ? false : Array.from(a).every((i) => b.has(i)),
44
- ),
45
- debounceTime(BATCH_DEBOUNCE_TIME),
46
- startWith(new Set<string>()),
47
- pairwise(),
48
- tap(([prevIds, currIds]) => {
49
- // for all new subscriptions, set their values to pending
50
- const newIds = [...currIds].filter((element) => !prevIds.has(element))
51
- state.set('updatingPending', (prev) => {
52
- const pendingValues = newIds.reduce<ProjectionStoreState['values']>((acc, id) => {
53
- const prevValue = prev.values[id]
54
- const value = prevValue?.data ? prevValue.data : null
55
- acc[id] = {data: value, isPending: true}
56
- return acc
57
- }, {})
58
- return {values: {...prev.values, ...pendingValues}}
31
+ const isSetEqual = <T>(a: Set<T>, b: Set<T>) =>
32
+ a.size === b.size && Array.from(a).every((i) => b.has(i))
33
+
34
+ export const subscribeToStateAndFetchBatches = ({
35
+ state,
36
+ instance,
37
+ }: StoreContext<ProjectionStoreState>): Subscription => {
38
+ const documentProjections$ = state.observable.pipe(
39
+ map((s) => s.documentProjections),
40
+ distinctUntilChanged(isEqual),
41
+ )
42
+
43
+ const activeDocumentIds$ = state.observable.pipe(
44
+ map(({subscriptions}) => new Set(Object.keys(subscriptions))),
45
+ distinctUntilChanged(isSetEqual),
46
+ )
47
+
48
+ const pendingUpdateSubscription = activeDocumentIds$
49
+ .pipe(
50
+ debounceTime(BATCH_DEBOUNCE_TIME),
51
+ startWith(new Set<string>()),
52
+ pairwise(),
53
+ tap(([prevIds, currIds]) => {
54
+ const newIds = [...currIds].filter((id) => !prevIds.has(id))
55
+ if (newIds.length === 0) return
56
+
57
+ state.set('updatingPending', (prev) => {
58
+ const nextValues = {...prev.values}
59
+ for (const id of newIds) {
60
+ const projectionsForDoc = prev.documentProjections[id]
61
+ if (!projectionsForDoc) continue
62
+
63
+ const currentValuesForDoc = prev.values[id] ?? {}
64
+ const updatedValuesForDoc = {...currentValuesForDoc}
65
+
66
+ for (const hash in projectionsForDoc) {
67
+ const currentValue = updatedValuesForDoc[hash]
68
+ updatedValuesForDoc[hash] = {
69
+ data: currentValue?.data ?? null,
70
+ isPending: true,
71
+ }
72
+ }
73
+ nextValues[id] = updatedValuesForDoc
74
+ }
75
+ return {values: nextValues}
76
+ })
77
+ }),
78
+ )
79
+ .subscribe()
80
+
81
+ const queryTrigger$ = combineLatest([activeDocumentIds$, documentProjections$]).pipe(
82
+ debounceTime(BATCH_DEBOUNCE_TIME),
83
+ distinctUntilChanged(isEqual),
84
+ )
85
+
86
+ const queryExecutionSubscription = queryTrigger$
87
+ .pipe(
88
+ switchMap(([ids, documentProjections]) => {
89
+ if (!ids.size) return EMPTY
90
+ const {query, params} = createProjectionQuery(ids, documentProjections)
91
+ const controller = new AbortController()
92
+
93
+ return new Observable<ProjectionQueryResult[]>((observer) => {
94
+ const {getCurrent, observable} = getQueryState<ProjectionQueryResult[]>(instance, query, {
95
+ params,
96
+ tag: PROJECTION_TAG,
97
+ perspective: PROJECTION_PERSPECTIVE,
59
98
  })
99
+
100
+ const source$ = defer(() => {
101
+ if (getCurrent() === undefined) {
102
+ return from(
103
+ resolveQuery<ProjectionQueryResult[]>(instance, query, {
104
+ params,
105
+ tag: PROJECTION_TAG,
106
+ perspective: PROJECTION_PERSPECTIVE,
107
+ signal: controller.signal,
108
+ }),
109
+ ).pipe(switchMap(() => observable))
110
+ }
111
+ return observable
112
+ }).pipe(filter((result): result is ProjectionQueryResult[] => result !== undefined))
113
+
114
+ const subscription = source$.subscribe(observer)
115
+
116
+ return () => {
117
+ if (!controller.signal.aborted) {
118
+ controller.abort()
119
+ }
120
+ subscription.unsubscribe()
121
+ }
122
+ }).pipe(map((data) => ({data, ids})))
123
+ }),
124
+ map(({ids, data}) =>
125
+ processProjectionQuery({
126
+ projectId: instance.config.projectId!,
127
+ dataset: instance.config.dataset!,
128
+ ids,
129
+ results: data,
60
130
  }),
61
- withLatestFrom(documentProjections$),
62
- map(([[, ids], documentProjections]) => ({ids, documentProjections})),
63
- )
64
-
65
- return combineLatest([newSubscriberIds$, lastLiveEventId$, client$])
66
- .pipe(
67
- switchMap(([{ids, documentProjections}, lastLiveEventId, client]) => {
68
- if (!ids.size) return EMPTY
69
- const {query, params} = createProjectionQuery(ids, documentProjections)
70
-
71
- return client.observable
72
- .fetch<ProjectionQueryResult[]>(query, params, {
73
- filterResponse: false,
74
- returnQuery: false,
75
- perspective: 'drafts',
76
- tag: PROJECTION_TAG,
77
- lastLiveEventId,
78
- })
79
- .pipe(map((response) => ({...response, ids})))
80
- }),
81
- map(({ids, result, syncTags}) => ({
82
- syncTags,
83
- values: processProjectionQuery({
84
- projectId: instance.identity.projectId,
85
- dataset: instance.identity.dataset,
86
- ids,
87
- results: result,
88
- }),
89
- })),
90
- )
91
- .subscribe({
92
- next: ({syncTags = [], values}) => {
93
- state.set('updateResult', (prev) => ({
94
- values: {...prev.values, ...values},
95
- syncTags: syncTags.reduce<Record<SyncTag, true>>((acc, next) => {
96
- acc[next] = true
97
- return acc
98
- }, {}),
99
- }))
100
- },
131
+ ),
132
+ )
133
+ .subscribe({
134
+ next: (processedValues) => {
135
+ state.set('updateResult', (prev) => {
136
+ const nextValues = {...prev.values}
137
+ for (const docId in processedValues) {
138
+ if (processedValues[docId]) {
139
+ nextValues[docId] = {
140
+ ...(prev.values[docId] ?? {}),
141
+ ...processedValues[docId],
142
+ }
143
+ }
144
+ }
145
+ return {values: nextValues}
101
146
  })
102
- }
103
- },
104
- )
147
+ },
148
+ error: (err) => {
149
+ // eslint-disable-next-line no-console
150
+ console.error('Error fetching projection batches:', err)
151
+ // TODO: Potentially update state to reflect error state for affected projections?
152
+ },
153
+ })
154
+
155
+ return new Subscription(() => {
156
+ pendingUpdateSubscription.unsubscribe()
157
+ queryExecutionSubscription.unsubscribe()
158
+ })
159
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @public
3
+ */
4
+ export type ValidProjection = `{${string}}`
5
+
6
+ /**
7
+ * @public
8
+ * The result of a projection query
9
+ */
10
+ export interface ProjectionValuePending<TValue extends object> {
11
+ data: TValue | null
12
+ isPending: boolean
13
+ }
14
+
15
+ export interface DocumentProjectionValues<TValue extends object = object> {
16
+ [projectionHash: string]: ProjectionValuePending<TValue>
17
+ }
18
+
19
+ export interface DocumentProjections {
20
+ [projectionHash: string]: ValidProjection
21
+ }
22
+
23
+ interface DocumentProjectionSubscriptions {
24
+ [projectionHash: string]: {
25
+ [subscriptionId: string]: true
26
+ }
27
+ }
28
+
29
+ export interface ProjectionStoreState<TValue extends object = object> {
30
+ /**
31
+ * A map of document IDs to their projection values, organized by projection hash
32
+ */
33
+ values: {
34
+ [documentId: string]: DocumentProjectionValues<TValue>
35
+ }
36
+
37
+ /**
38
+ * A map of document IDs to their projections, organized by projection hash
39
+ */
40
+ documentProjections: {
41
+ [documentId: string]: DocumentProjections
42
+ }
43
+
44
+ /**
45
+ * A map of document IDs to their subscriptions, organized by projection hash
46
+ */
47
+ subscriptions: {
48
+ [documentId: string]: DocumentProjectionSubscriptions
49
+ }
50
+ }
@@ -1,6 +1,8 @@
1
- import {type ValidProjection} from './projectionStore'
1
+ import {type ValidProjection} from './types'
2
2
 
3
3
  export const PROJECTION_TAG = 'sdk.projection'
4
+ export const PROJECTION_PERSPECTIVE = 'drafts'
5
+ export const PROJECTION_STATE_CLEAR_DELAY = 1000
4
6
 
5
7
  export const STABLE_EMPTY_PROJECTION = {
6
8
  data: null,
@@ -1,17 +1,26 @@
1
1
  import {type SanityClient} from '@sanity/client'
2
2
  import {of} from 'rxjs'
3
- import {describe, it} from 'vitest'
3
+ import {afterEach, beforeEach, describe, it} from 'vitest'
4
4
 
5
5
  import {getClientState} from '../client/clientStore'
6
- import {createSanityInstance} from '../instance/sanityInstance'
7
- import {type StateSource} from '../resources/createStateSourceAction'
6
+ import {createSanityInstance, type SanityInstance} from '../store/createSanityInstance'
7
+ import {type StateSource} from '../store/createStateSourceAction'
8
8
  import {resolveProjects} from './projects'
9
9
 
10
10
  vi.mock('../client/clientStore')
11
11
 
12
12
  describe('projects', () => {
13
+ let instance: SanityInstance
14
+
15
+ beforeEach(() => {
16
+ instance = createSanityInstance({projectId: 'p', dataset: 'd'})
17
+ })
18
+
19
+ afterEach(() => {
20
+ instance.dispose()
21
+ })
22
+
13
23
  it('calls the `client.observable.projects.list` method on the client and returns the result', async () => {
14
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
15
24
  const projects = [{id: 'a'}, {id: 'b'}]
16
25
  const list = vi.fn().mockReturnValue(of(projects))
17
26
 
@@ -3,11 +3,16 @@ import {switchMap} from 'rxjs'
3
3
  import {getClientState} from '../client/clientStore'
4
4
  import {createFetcherStore} from '../utils/createFetcherStore'
5
5
 
6
+ const API_VERSION = 'v2025-02-19'
7
+
6
8
  const projects = createFetcherStore({
7
9
  name: 'Projects',
8
10
  getKey: () => 'projects',
9
11
  fetcher: (instance) => () =>
10
- getClientState(instance, {apiVersion: 'vX', scope: 'global'}).observable.pipe(
12
+ getClientState(instance, {
13
+ apiVersion: API_VERSION,
14
+ scope: 'global',
15
+ }).observable.pipe(
11
16
  switchMap((client) => client.observable.projects.list({includeMembers: false})),
12
17
  ),
13
18
  })
@@ -3,10 +3,9 @@ import {delay, filter, firstValueFrom, Observable, of, Subject} from 'rxjs'
3
3
  import {beforeEach, describe, expect, it, vi} from 'vitest'
4
4
 
5
5
  import {getClientState} from '../client/clientStore'
6
- import {createSanityInstance} from '../instance/sanityInstance'
7
- import {getOrCreateResource} from '../resources/createResource'
8
- import {type StateSource} from '../resources/createStateSourceAction'
9
- import {errorHandler, getQueryState, queryStore, resolveQuery} from './queryStore'
6
+ import {createSanityInstance, type SanityInstance} from '../store/createSanityInstance'
7
+ import {type StateSource} from '../store/createStateSourceAction'
8
+ import {getQueryState, resolveQuery} from './queryStore'
10
9
 
11
10
  vi.mock('./queryStoreConstants', async (importOriginal) => ({
12
11
  ...(await importOriginal<typeof import('./queryStoreConstants')>()),
@@ -18,6 +17,7 @@ vi.mock('../client/clientStore', () => ({
18
17
  }))
19
18
 
20
19
  describe('queryStore', () => {
20
+ let instance: SanityInstance
21
21
  let liveEvents: Subject<LiveEvent>
22
22
  let fetch: SanityClient['observable']['fetch']
23
23
  // Mock data for testing
@@ -29,6 +29,8 @@ describe('queryStore', () => {
29
29
  }
30
30
 
31
31
  beforeEach(() => {
32
+ instance = createSanityInstance({projectId: 'test', dataset: 'test'})
33
+
32
34
  fetch = vi
33
35
  .fn()
34
36
  .mockReturnValue(
@@ -50,8 +52,11 @@ describe('queryStore', () => {
50
52
  } as StateSource<SanityClient>)
51
53
  })
52
54
 
55
+ afterEach(() => {
56
+ instance.dispose()
57
+ })
58
+
53
59
  it('initializes query state and cleans up after unsubscribe', async () => {
54
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
55
60
  const query = '*[_type == "movie"]'
56
61
  const state = getQueryState(instance, query)
57
62
 
@@ -78,12 +83,9 @@ describe('queryStore', () => {
78
83
 
79
84
  // Verify state is cleared
80
85
  expect(state.getCurrent()).toBeUndefined()
81
-
82
- instance.dispose()
83
86
  })
84
87
 
85
88
  it('maintains state when multiple subscribers exist', async () => {
86
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
87
89
  const query = '*[_type == "movie"]'
88
90
  const state = getQueryState(instance, query)
89
91
 
@@ -117,12 +119,9 @@ describe('queryStore', () => {
117
119
 
118
120
  // Verify state is cleared after all subscribers are gone
119
121
  expect(state.getCurrent()).toBeUndefined()
120
-
121
- instance.dispose()
122
122
  })
123
123
 
124
124
  it('resolveQuery works without affecting subscriber cleanup', async () => {
125
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
126
125
  const query = '*[_type == "movie"]'
127
126
 
128
127
  const state = getQueryState(instance, query)
@@ -151,12 +150,9 @@ describe('queryStore', () => {
151
150
  unsubscribe()
152
151
  await new Promise((resolve) => setTimeout(resolve, 20))
153
152
  expect(state.getCurrent()).toBeUndefined()
154
-
155
- instance.dispose()
156
153
  })
157
154
 
158
155
  it('handles abort signal in resolveQuery', async () => {
159
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
160
156
  const query = '*[_type == "movie"]'
161
157
  const abortController = new AbortController()
162
158
 
@@ -171,8 +167,6 @@ describe('queryStore', () => {
171
167
 
172
168
  // Verify state is cleared after abort
173
169
  expect(getQueryState(instance, query).getCurrent()).toBeUndefined()
174
-
175
- instance.dispose()
176
170
  })
177
171
 
178
172
  it('refetches query when receiving live event with matching sync tag', async () => {
@@ -190,7 +184,6 @@ describe('queryStore', () => {
190
184
  ),
191
185
  )
192
186
 
193
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
194
187
  const query = '*[_type == "movie"]'
195
188
  const state = getQueryState<{_id: string; _type: string; title: string}[]>(instance, query)
196
189
 
@@ -214,7 +207,6 @@ describe('queryStore', () => {
214
207
  expect(result).toContainEqual(updatedMovie)
215
208
 
216
209
  unsubscribe()
217
- instance.dispose()
218
210
  })
219
211
 
220
212
  it('does not refetch for non-matching sync tags', async () => {
@@ -223,7 +215,6 @@ describe('queryStore', () => {
223
215
  of({result: mockData.movies, syncTags: mockSyncTags, ms: 0}).pipe(delay(0)),
224
216
  )
225
217
 
226
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
227
218
  const query = '*[_type == "movie"]'
228
219
  const state = getQueryState(instance, query)
229
220
 
@@ -243,7 +234,6 @@ describe('queryStore', () => {
243
234
  expect(fetch).toHaveBeenCalledTimes(1)
244
235
 
245
236
  unsubscribe()
246
- instance.dispose()
247
237
  })
248
238
 
249
239
  it('handles multiple live events with same sync tag', async () => {
@@ -258,7 +248,6 @@ describe('queryStore', () => {
258
248
  of({result: mockData.movies, syncTags: mockSyncTags, ms: 0}).pipe(delay(0)),
259
249
  )
260
250
 
261
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
262
251
  const query = '*[_type == "movie"]'
263
252
  const state = getQueryState(instance, query)
264
253
 
@@ -284,11 +273,9 @@ describe('queryStore', () => {
284
273
  expect(vi.mocked(fetch).mock.calls[2][2]?.lastLiveEventId).toBe('event2')
285
274
 
286
275
  unsubscribe()
287
- instance.dispose()
288
276
  })
289
277
 
290
278
  it('handles errors in query fetching', async () => {
291
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
292
279
  const errorMessage = 'Query failed'
293
280
 
294
281
  // Override fetch to simulate error
@@ -306,29 +293,9 @@ describe('queryStore', () => {
306
293
  expect(() => state.getCurrent()).toThrow(errorMessage)
307
294
 
308
295
  unsubscribe()
309
- instance.dispose()
310
- })
311
-
312
- it('throws an error if an errorHandler has been called', () => {
313
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
314
- const query = '*[_type == "movie"]'
315
- const state = getQueryState(instance, query)
316
-
317
- const resource = getOrCreateResource(instance, queryStore)
318
-
319
- // Create an error and call the error handler
320
- const testError = new Error('Global error from error handler')
321
- const handler = errorHandler({state: resource.state, instance})
322
- handler(testError)
323
-
324
- // Verify the error is thrown when accessing state
325
- expect(() => state.getCurrent()).toThrow('Global error from error handler')
326
-
327
- instance.dispose()
328
296
  })
329
297
 
330
298
  it('delays query state removal after unsubscribe', async () => {
331
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
332
299
  const query = '*[_type == "movie"]'
333
300
  const state = getQueryState(instance, query)
334
301
  const unsubscribe = state.subscribe()
@@ -342,12 +309,9 @@ describe('queryStore', () => {
342
309
  // Wait for the cleanup delay and then state should be removed
343
310
  await new Promise((resolve) => setTimeout(resolve, 20))
344
311
  expect(state.getCurrent()).toBeUndefined()
345
-
346
- instance.dispose()
347
312
  })
348
313
 
349
314
  it('preserves query state if a new subscriber subscribes before cleanup delay', async () => {
350
- const instance = createSanityInstance({projectId: 'test', dataset: 'test'})
351
315
  const query = '*[_type == "movie"]'
352
316
  const state = getQueryState(instance, query)
353
317
  const unsubscribe1 = state.subscribe()
@@ -374,6 +338,5 @@ describe('queryStore', () => {
374
338
  {_id: 'movie2', _type: 'movie', title: 'Movie 2'},
375
339
  ])
376
340
  unsubscribe2()
377
- instance.dispose()
378
341
  })
379
342
  })