@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,48 +1,67 @@
1
1
  import {describe, expect, it} from 'vitest'
2
2
 
3
3
  import {createProjectionQuery, processProjectionQuery} from './projectionQuery'
4
+ import {type ValidProjection} from './types'
4
5
 
5
6
  describe('createProjectionQuery', () => {
6
7
  it('creates a query and params for given ids and projections', () => {
7
8
  const ids = new Set(['doc1', 'doc2'])
9
+ const projectionHash: ValidProjection = '{title, description}'
8
10
  const documentProjections = {
9
- doc1: '{title, description}',
10
- doc2: '{title, description}',
11
+ doc1: {[projectionHash]: projectionHash},
12
+ doc2: {[projectionHash]: projectionHash},
11
13
  }
12
14
 
13
15
  const {query, params} = createProjectionQuery(ids, documentProjections)
14
16
  expect(query).toMatch(/.*_id in \$__ids_.*/)
15
17
  expect(Object.keys(params)).toHaveLength(1)
18
+ expect(params[`__ids_${projectionHash}`]).toBeDefined()
19
+ expect(params[`__ids_${projectionHash}`]).toHaveLength(4)
16
20
  })
17
21
 
18
22
  it('handles multiple different projections', () => {
19
23
  const ids = new Set(['doc1', 'doc2'])
24
+ const projectionHash1: ValidProjection = '{title, description}'
25
+ const projectionHash2: ValidProjection = '{name, age}'
20
26
  const documentProjections = {
21
- doc1: '{title, description}',
22
- doc2: '{name, age}',
27
+ doc1: {[projectionHash1]: projectionHash1},
28
+ doc2: {[projectionHash2]: projectionHash2},
23
29
  }
24
30
 
25
31
  const {query, params} = createProjectionQuery(ids, documentProjections)
26
32
  expect(query).toMatch(/.*_id in \$__ids_.*/)
27
33
  expect(Object.keys(params)).toHaveLength(2)
34
+ expect(params[`__ids_${projectionHash1}`]).toBeDefined()
35
+ expect(params[`__ids_${projectionHash1}`]).toHaveLength(2)
36
+ expect(params[`__ids_${projectionHash2}`]).toBeDefined()
37
+ expect(params[`__ids_${projectionHash2}`]).toHaveLength(2)
28
38
  })
29
39
 
30
40
  it('filters out ids without projections', () => {
31
41
  const ids = new Set(['doc1', 'doc2', 'doc3'])
42
+ const projectionHash1: ValidProjection = '{title}'
43
+ // projectionHash2 missing intentionally
44
+ const projectionHash3: ValidProjection = '{name}'
45
+
32
46
  const documentProjections = {
33
- doc1: '{title}',
34
- // doc2 missing intentionally
35
- doc3: '{name}',
47
+ doc1: {[projectionHash1]: projectionHash1},
48
+ doc3: {[projectionHash3]: projectionHash3},
36
49
  }
37
50
 
38
51
  const {query, params} = createProjectionQuery(ids, documentProjections)
39
52
  expect(query).toMatch(/.*_id in \$__ids_.*/)
40
53
  expect(Object.keys(params)).toHaveLength(2)
54
+ expect(params[`__ids_${projectionHash1}`]).toBeDefined()
55
+ expect(params[`__ids_${projectionHash1}`]).toHaveLength(2)
56
+ expect(params[`__ids_${projectionHash3}`]).toBeDefined()
57
+ expect(params[`__ids_${projectionHash3}`]).toHaveLength(2)
41
58
  })
42
59
  })
43
60
 
44
61
  describe('processProjectionQuery', () => {
45
- it('returns null if no results found', () => {
62
+ const testProjectionHash = '{...}'
63
+
64
+ it('returns structure with empty object if no results found', () => {
46
65
  const ids = new Set(['doc1'])
47
66
  const result = processProjectionQuery({
48
67
  projectId: 'p',
@@ -51,7 +70,39 @@ describe('processProjectionQuery', () => {
51
70
  results: [], // no results
52
71
  })
53
72
 
54
- expect(result['doc1']).toEqual({data: null, isPending: false})
73
+ expect(result['doc1']).toEqual({})
74
+ })
75
+
76
+ it('returns structure with isPending:false and null data for ids with no results', () => {
77
+ const ids = new Set(['doc1', 'doc2'])
78
+ const results = [
79
+ {
80
+ _id: 'doc1',
81
+ _type: 'document',
82
+ _updatedAt: '2021-01-01',
83
+ result: {title: 'Hello', description: 'World'},
84
+ __projectionHash: testProjectionHash,
85
+ },
86
+ ]
87
+
88
+ const processed = processProjectionQuery({
89
+ projectId: 'p',
90
+ dataset: 'd',
91
+ ids,
92
+ results,
93
+ })
94
+
95
+ expect(processed['doc1']?.[testProjectionHash]).toEqual({
96
+ data: {
97
+ title: 'Hello',
98
+ description: 'World',
99
+ status: {
100
+ lastEditedPublishedAt: '2021-01-01',
101
+ },
102
+ },
103
+ isPending: false,
104
+ })
105
+ expect(processed['doc2']).toEqual({})
55
106
  })
56
107
 
57
108
  it('processes query results into projection values', () => {
@@ -61,6 +112,7 @@ describe('processProjectionQuery', () => {
61
112
  _type: 'document',
62
113
  _updatedAt: '2021-01-01',
63
114
  result: {title: 'Hello', description: 'World'},
115
+ __projectionHash: testProjectionHash,
64
116
  },
65
117
  ]
66
118
 
@@ -71,7 +123,7 @@ describe('processProjectionQuery', () => {
71
123
  results,
72
124
  })
73
125
 
74
- expect(processed['doc1']).toEqual({
126
+ expect(processed['doc1']?.[testProjectionHash]).toEqual({
75
127
  data: {
76
128
  title: 'Hello',
77
129
  description: 'World',
@@ -90,12 +142,14 @@ describe('processProjectionQuery', () => {
90
142
  _type: 'document',
91
143
  _updatedAt: '2021-01-02',
92
144
  result: {title: 'Draft'},
145
+ __projectionHash: testProjectionHash,
93
146
  },
94
147
  {
95
148
  _id: 'doc1',
96
149
  _type: 'document',
97
150
  _updatedAt: '2021-01-01',
98
151
  result: {title: 'Published'},
152
+ __projectionHash: testProjectionHash,
99
153
  },
100
154
  ]
101
155
 
@@ -106,7 +160,7 @@ describe('processProjectionQuery', () => {
106
160
  results,
107
161
  })
108
162
 
109
- expect(processed['doc1']).toEqual({
163
+ expect(processed['doc1']?.[testProjectionHash]).toEqual({
110
164
  data: {
111
165
  title: 'Draft',
112
166
  status: {
@@ -125,6 +179,7 @@ describe('processProjectionQuery', () => {
125
179
  _type: 'document',
126
180
  _updatedAt: '2021-01-01',
127
181
  result: {title: 'Published'},
182
+ __projectionHash: testProjectionHash,
128
183
  },
129
184
  ]
130
185
 
@@ -135,7 +190,7 @@ describe('processProjectionQuery', () => {
135
190
  results,
136
191
  })
137
192
 
138
- expect(processed['doc1']).toEqual({
193
+ expect(processed['doc1']?.[testProjectionHash]).toEqual({
139
194
  data: {
140
195
  title: 'Published',
141
196
  status: {
@@ -145,4 +200,51 @@ describe('processProjectionQuery', () => {
145
200
  isPending: false,
146
201
  })
147
202
  })
203
+
204
+ it('handles multiple projections for the same document', () => {
205
+ const hash1 = '{title}'
206
+ const hash2 = '{description}'
207
+ const results = [
208
+ {
209
+ _id: 'doc1',
210
+ _type: 'document',
211
+ _updatedAt: '2021-01-01',
212
+ result: {title: 'Published Title'},
213
+ __projectionHash: hash1,
214
+ },
215
+ {
216
+ _id: 'doc1',
217
+ _type: 'document',
218
+ _updatedAt: '2021-01-01',
219
+ result: {description: 'Published Desc'},
220
+ __projectionHash: hash2,
221
+ },
222
+ ]
223
+
224
+ const processed = processProjectionQuery({
225
+ projectId: 'p',
226
+ dataset: 'd',
227
+ ids: new Set(['doc1']),
228
+ results,
229
+ })
230
+
231
+ expect(processed['doc1']?.[hash1]).toEqual({
232
+ data: {
233
+ title: 'Published Title',
234
+ status: {
235
+ lastEditedPublishedAt: '2021-01-01',
236
+ },
237
+ },
238
+ isPending: false,
239
+ })
240
+ expect(processed['doc1']?.[hash2]).toEqual({
241
+ data: {
242
+ description: 'Published Desc',
243
+ status: {
244
+ lastEditedPublishedAt: '2021-01-01',
245
+ },
246
+ },
247
+ isPending: false,
248
+ })
249
+ })
148
250
  })
@@ -1,13 +1,16 @@
1
- import {hashString} from '../common/util'
2
1
  import {getDraftId, getPublishedId} from '../utils/ids'
3
- import {type ProjectionValuePending, type ValidProjection} from './projectionStore'
4
- import {validateProjection} from './util'
2
+ import {
3
+ type DocumentProjections,
4
+ type DocumentProjectionValues,
5
+ type ValidProjection,
6
+ } from './types'
5
7
 
6
- type ProjectionQueryResult = {
8
+ export type ProjectionQueryResult = {
7
9
  _id: string
8
10
  _type: string
9
11
  _updatedAt: string
10
12
  result: Record<string, unknown>
13
+ __projectionHash: string
11
14
  }
12
15
 
13
16
  interface CreateProjectionQueryResult {
@@ -19,14 +22,18 @@ type ProjectionMap = Record<string, {projection: ValidProjection; documentIds: S
19
22
 
20
23
  export function createProjectionQuery(
21
24
  documentIds: Set<string>,
22
- documentProjections: {[TDocumentId in string]?: string},
25
+ documentProjections: {[TDocumentId in string]?: DocumentProjections},
23
26
  ): CreateProjectionQueryResult {
24
27
  const projections = Array.from(documentIds)
25
- .filter((id) => documentProjections[id])
26
- .map((id) => {
27
- const projection = validateProjection(documentProjections[id]!)
28
- const projectionHash = hashString(projection)
29
- return {documentId: id, projection, projectionHash}
28
+ .flatMap((id) => {
29
+ const projectionsForDoc = documentProjections[id]
30
+ if (!projectionsForDoc) return []
31
+
32
+ return Object.entries(projectionsForDoc).map(([projectionHash, projection]) => ({
33
+ documentId: id,
34
+ projection,
35
+ projectionHash,
36
+ }))
30
37
  })
31
38
  .reduce<ProjectionMap>((acc, {documentId, projection, projectionHash}) => {
32
39
  const obj = acc[projectionHash] ?? {documentIds: new Set(), projection}
@@ -38,7 +45,7 @@ export function createProjectionQuery(
38
45
 
39
46
  const query = `[${Object.entries(projections)
40
47
  .map(([projectionHash, {projection}]) => {
41
- return `...*[_id in $__ids_${projectionHash}]{_id,_type,_updatedAt,"result":{...${projection}}}`
48
+ return `...*[_id in $__ids_${projectionHash}]{_id,_type,_updatedAt,"__projectionHash":"${projectionHash}","result":{...${projection}}}`
42
49
  })
43
50
  .join(',')}]`
44
51
 
@@ -64,33 +71,69 @@ interface ProcessProjectionQueryOptions {
64
71
  }
65
72
 
66
73
  export function processProjectionQuery({ids, results}: ProcessProjectionQueryOptions): {
67
- [TDocumentId in string]?: ProjectionValuePending<Record<string, unknown>>
74
+ [TDocumentId in string]?: DocumentProjectionValues<Record<string, unknown>>
68
75
  } {
69
- const resultMap = results.reduce<{[TDocumentId in string]?: ProjectionQueryResult}>(
70
- (acc, next) => {
71
- acc[next._id] = next
72
- return acc
73
- },
74
- {},
75
- )
76
+ const groupedResults: {
77
+ [docId: string]: {
78
+ [hash: string]: {
79
+ draft?: ProjectionQueryResult
80
+ published?: ProjectionQueryResult
81
+ }
82
+ }
83
+ } = {}
84
+
85
+ for (const result of results) {
86
+ const originalId = getPublishedId(result._id)
87
+ const hash = result.__projectionHash
88
+ const isDraft = result._id.startsWith('drafts.')
89
+
90
+ if (!ids.has(originalId)) continue
91
+
92
+ if (!groupedResults[originalId]) {
93
+ groupedResults[originalId] = {}
94
+ }
95
+ if (!groupedResults[originalId][hash]) {
96
+ groupedResults[originalId][hash] = {}
97
+ }
98
+
99
+ if (isDraft) {
100
+ groupedResults[originalId][hash].draft = result
101
+ } else {
102
+ groupedResults[originalId][hash].published = result
103
+ }
104
+ }
105
+
106
+ const finalValues: {
107
+ [docId: string]: DocumentProjectionValues<Record<string, unknown>>
108
+ } = {}
76
109
 
77
- return Object.fromEntries(
78
- Array.from(ids).map((id): [string, ProjectionValuePending<Record<string, unknown>>] => {
79
- const publishedId = getPublishedId(id)
80
- const draftId = getDraftId(id)
110
+ for (const originalId of ids) {
111
+ finalValues[originalId] = {}
81
112
 
82
- const draftResult = resultMap[draftId]
83
- const publishedResult = resultMap[publishedId]
113
+ const projectionsForDoc = groupedResults[originalId]
114
+ if (!projectionsForDoc) continue
84
115
 
85
- const projectionResult = draftResult?.result ?? publishedResult?.result
86
- if (!projectionResult) return [id, {data: null, isPending: false}]
116
+ for (const hash in projectionsForDoc) {
117
+ const {draft, published} = projectionsForDoc[hash]
118
+
119
+ const projectionResultData = draft?.result ?? published?.result
120
+
121
+ if (!projectionResultData) {
122
+ finalValues[originalId][hash] = {data: null, isPending: false}
123
+ continue
124
+ }
87
125
 
88
126
  const status = {
89
- ...(draftResult?._updatedAt && {lastEditedDraftAt: draftResult._updatedAt}),
90
- ...(publishedResult?._updatedAt && {lastEditedPublishedAt: publishedResult._updatedAt}),
127
+ ...(draft?._updatedAt && {lastEditedDraftAt: draft._updatedAt}),
128
+ ...(published?._updatedAt && {lastEditedPublishedAt: published._updatedAt}),
91
129
  }
92
130
 
93
- return [id, {data: {...projectionResult, status}, isPending: false}]
94
- }),
95
- )
131
+ finalValues[originalId][hash] = {
132
+ data: {...projectionResultData, status},
133
+ isPending: false,
134
+ }
135
+ }
136
+ }
137
+
138
+ return finalValues
96
139
  }
@@ -1,11 +1,10 @@
1
- import {type Subscription} from 'rxjs'
2
- import {describe, expect, it, type Mock, vi} from 'vitest'
1
+ import {Observable} from 'rxjs'
2
+ import {describe, it, vi} from 'vitest'
3
3
 
4
- import {createSanityInstance} from '../instance/sanityInstance'
5
- import {createResourceState} from '../resources/createResource'
4
+ import {createSanityInstance} from '../store/createSanityInstance'
5
+ import {createStoreInstance} from '../store/createStoreInstance'
6
6
  import {projectionStore} from './projectionStore'
7
7
  import {subscribeToStateAndFetchBatches} from './subscribeToStateAndFetchBatches'
8
- import {PROJECTION_TAG} from './util'
9
8
 
10
9
  // Mock the module with a factory function
11
10
  vi.mock('../common/createLiveEventSubscriber', () => {
@@ -15,61 +14,24 @@ vi.mock('../common/createLiveEventSubscriber', () => {
15
14
  }
16
15
  })
17
16
 
18
- vi.mock('./subscribeToStateAndFetchBatches', () => ({
19
- subscribeToStateAndFetchBatches: vi.fn(),
20
- }))
17
+ vi.mock('./subscribeToStateAndFetchBatches')
21
18
 
22
19
  describe('projectionStore', () => {
23
20
  it('is a resource that initializes with state and subscriptions', async () => {
24
- const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
25
- const initialState = projectionStore.getInitialState(instance)
26
-
27
- expect(initialState).toEqual({
28
- values: {},
29
- documentProjections: {},
30
- subscriptions: {},
31
- syncTags: {},
32
- lastLiveEventId: null,
33
- })
34
-
35
- const liveUnsubscribe = vi.fn()
36
- const stateUnsubscribe = vi.fn()
37
-
38
- const {createLiveEventSubscriber} = vi.mocked(
39
- await import('../common/createLiveEventSubscriber'),
21
+ const teardown = vi.fn()
22
+ const subscriber = vi.fn().mockReturnValue(teardown)
23
+ vi.mocked(subscribeToStateAndFetchBatches).mockReturnValue(
24
+ new Observable(subscriber).subscribe(),
40
25
  )
41
- const mockLiveSubscriber = vi
42
- .mocked(createLiveEventSubscriber(PROJECTION_TAG))
43
- .mockReturnValue({
44
- unsubscribe: liveUnsubscribe,
45
- } as unknown as Subscription)
46
-
47
- ;(subscribeToStateAndFetchBatches as Mock).mockImplementation(() => ({
48
- unsubscribe: stateUnsubscribe,
49
- }))
50
26
 
51
- const dispose = projectionStore.initialize!.call(
52
- {
53
- instance,
54
- state: createResourceState(initialState),
55
- },
56
- instance,
57
- )
58
-
59
- // Verify the factory was called with the correct tag
60
- expect(createLiveEventSubscriber).toHaveBeenCalledWith(PROJECTION_TAG)
27
+ const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
61
28
 
62
- // Verify the subscriber was called with the correct context
63
- expect(mockLiveSubscriber).toHaveBeenCalledWith({
64
- instance,
65
- state: expect.any(Object),
66
- })
29
+ const {state, dispose} = createStoreInstance(instance, projectionStore)
67
30
 
68
31
  expect(subscribeToStateAndFetchBatches).toHaveBeenCalledOnce()
32
+ expect(subscribeToStateAndFetchBatches).toHaveBeenCalledWith({instance, state})
69
33
 
70
34
  dispose()
71
-
72
- expect(liveUnsubscribe).toHaveBeenCalledOnce()
73
- expect(stateUnsubscribe).toHaveBeenCalledOnce()
35
+ instance.dispose()
74
36
  })
75
37
  })
@@ -1,55 +1,18 @@
1
- import {createLiveEventSubscriber} from '../common/createLiveEventSubscriber'
2
- import {type LiveEventAwareState} from '../common/types'
3
- import {createResource} from '../resources/createResource'
1
+ import {defineStore} from '../store/defineStore'
4
2
  import {subscribeToStateAndFetchBatches} from './subscribeToStateAndFetchBatches'
5
- import {PROJECTION_TAG} from './util'
3
+ import {type ProjectionStoreState} from './types'
6
4
 
7
- /**
8
- * @beta
9
- */
10
- export type ValidProjection = `{${string}}`
11
-
12
- export interface ProjectionQueryResult<TValue = Record<string, unknown>> {
13
- _id: string
14
- _type: string
15
- _updatedAt: string
16
- result: TValue
17
- }
18
-
19
- /**
20
- * @beta
21
- */
22
- export interface ProjectionValuePending<TValue extends object> {
23
- data: TValue | null
24
- isPending: boolean
25
- }
26
-
27
- export interface ProjectionStoreState<TValue extends object = object> extends LiveEventAwareState {
28
- values: {[TDocumentId in string]?: ProjectionValuePending<TValue>}
29
- documentProjections: {[TDocumentId in string]?: ValidProjection}
30
- subscriptions: {[TDocumentId in string]?: {[TSubscriptionId in string]?: true}}
31
- }
32
-
33
- export const projectionStore = createResource<ProjectionStoreState>({
5
+ export const projectionStore = defineStore<ProjectionStoreState>({
34
6
  name: 'Projection',
35
7
  getInitialState() {
36
8
  return {
37
9
  values: {},
38
10
  documentProjections: {},
39
11
  subscriptions: {},
40
- syncTags: {},
41
- lastLiveEventId: null,
42
12
  }
43
13
  },
44
- initialize() {
45
- const subscribeToLiveAndSetLastLiveEventId =
46
- createLiveEventSubscriber<ProjectionStoreState>(PROJECTION_TAG)
47
- const liveSubscription = subscribeToLiveAndSetLastLiveEventId(this)
48
- const batchSubscription = subscribeToStateAndFetchBatches(this)
49
-
50
- return () => {
51
- liveSubscription.unsubscribe()
52
- batchSubscription.unsubscribe()
53
- }
14
+ initialize(context) {
15
+ const batchSubscription = subscribeToStateAndFetchBatches(context)
16
+ return () => batchSubscription.unsubscribe()
54
17
  },
55
18
  })