@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.
- package/dist/index.d.ts +441 -322
- package/dist/index.js +1685 -1481
- package/dist/index.js.map +1 -1
- package/package.json +13 -15
- package/src/_exports/index.ts +32 -30
- package/src/auth/authStore.test.ts +149 -104
- package/src/auth/authStore.ts +51 -100
- package/src/auth/handleAuthCallback.test.ts +67 -34
- package/src/auth/handleAuthCallback.ts +8 -7
- package/src/auth/logout.test.ts +61 -29
- package/src/auth/logout.ts +26 -28
- package/src/auth/refreshStampedToken.test.ts +197 -91
- package/src/auth/refreshStampedToken.ts +170 -59
- package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +5 -5
- package/src/auth/subscribeToStateAndFetchCurrentUser.ts +45 -47
- package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +4 -5
- package/src/auth/subscribeToStorageEventsAndSetToken.ts +22 -24
- package/src/client/clientStore.test.ts +131 -67
- package/src/client/clientStore.ts +117 -116
- package/src/comlink/controller/actions/destroyController.test.ts +38 -13
- package/src/comlink/controller/actions/destroyController.ts +11 -15
- package/src/comlink/controller/actions/getOrCreateChannel.test.ts +56 -27
- package/src/comlink/controller/actions/getOrCreateChannel.ts +37 -35
- package/src/comlink/controller/actions/getOrCreateController.test.ts +27 -16
- package/src/comlink/controller/actions/getOrCreateController.ts +23 -22
- package/src/comlink/controller/actions/releaseChannel.test.ts +37 -13
- package/src/comlink/controller/actions/releaseChannel.ts +22 -21
- package/src/comlink/controller/comlinkControllerStore.test.ts +65 -36
- package/src/comlink/controller/comlinkControllerStore.ts +44 -5
- package/src/comlink/node/actions/getOrCreateNode.test.ts +31 -15
- package/src/comlink/node/actions/getOrCreateNode.ts +30 -29
- package/src/comlink/node/actions/releaseNode.test.ts +75 -55
- package/src/comlink/node/actions/releaseNode.ts +19 -21
- package/src/comlink/node/comlinkNodeStore.test.ts +6 -11
- package/src/comlink/node/comlinkNodeStore.ts +22 -5
- package/src/config/authConfig.ts +79 -0
- package/src/config/sanityConfig.ts +48 -0
- package/src/datasets/datasets.test.ts +2 -2
- package/src/datasets/datasets.ts +18 -5
- package/src/document/actions.test.ts +22 -10
- package/src/document/actions.ts +44 -56
- package/src/document/applyDocumentActions.test.ts +96 -36
- package/src/document/applyDocumentActions.ts +140 -99
- package/src/document/documentStore.test.ts +103 -155
- package/src/document/documentStore.ts +247 -238
- package/src/document/listen.ts +56 -55
- package/src/document/patchOperations.ts +0 -43
- package/src/document/permissions.test.ts +25 -12
- package/src/document/permissions.ts +11 -4
- package/src/document/processActions.test.ts +41 -8
- package/src/document/reducers.test.ts +87 -16
- package/src/document/reducers.ts +2 -2
- package/src/document/sharedListener.test.ts +34 -16
- package/src/document/sharedListener.ts +33 -11
- package/src/preview/getPreviewState.test.ts +40 -39
- package/src/preview/getPreviewState.ts +68 -56
- package/src/preview/previewConstants.ts +43 -0
- package/src/preview/previewQuery.test.ts +1 -1
- package/src/preview/previewQuery.ts +4 -5
- package/src/preview/previewStore.test.ts +13 -58
- package/src/preview/previewStore.ts +7 -21
- package/src/preview/resolvePreview.test.ts +33 -104
- package/src/preview/resolvePreview.ts +11 -21
- package/src/preview/subscribeToStateAndFetchBatches.test.ts +96 -97
- package/src/preview/subscribeToStateAndFetchBatches.ts +85 -81
- package/src/preview/util.ts +1 -0
- package/src/project/project.test.ts +3 -3
- package/src/project/project.ts +28 -5
- package/src/projection/getProjectionState.test.ts +188 -72
- package/src/projection/getProjectionState.ts +92 -62
- package/src/projection/projectionQuery.test.ts +114 -12
- package/src/projection/projectionQuery.ts +75 -32
- package/src/projection/projectionStore.test.ts +13 -51
- package/src/projection/projectionStore.ts +6 -43
- package/src/projection/resolveProjection.test.ts +32 -127
- package/src/projection/resolveProjection.ts +16 -28
- package/src/projection/subscribeToStateAndFetchBatches.test.ts +203 -116
- package/src/projection/subscribeToStateAndFetchBatches.ts +140 -85
- package/src/projection/types.ts +50 -0
- package/src/projection/util.ts +3 -1
- package/src/projects/projects.test.ts +13 -4
- package/src/projects/projects.ts +6 -1
- package/src/query/queryStore.test.ts +10 -47
- package/src/query/queryStore.ts +151 -133
- package/src/query/queryStoreConstants.ts +2 -0
- package/src/store/createActionBinder.test.ts +153 -0
- package/src/store/createActionBinder.ts +176 -0
- package/src/store/createSanityInstance.test.ts +84 -0
- package/src/store/createSanityInstance.ts +124 -0
- package/src/store/createStateSourceAction.test.ts +196 -0
- package/src/store/createStateSourceAction.ts +260 -0
- package/src/store/createStoreInstance.test.ts +81 -0
- package/src/store/createStoreInstance.ts +80 -0
- package/src/store/createStoreState.test.ts +85 -0
- package/src/store/createStoreState.ts +92 -0
- package/src/store/defineStore.test.ts +18 -0
- package/src/store/defineStore.ts +81 -0
- package/src/users/reducers.test.ts +318 -0
- package/src/users/reducers.ts +88 -0
- package/src/users/types.ts +46 -4
- package/src/users/usersConstants.ts +4 -0
- package/src/users/usersStore.test.ts +350 -223
- package/src/users/usersStore.ts +285 -149
- package/src/utils/createFetcherStore.test.ts +6 -7
- package/src/utils/createFetcherStore.ts +150 -153
- package/src/utils/createGroqSearchFilter.test.ts +75 -0
- package/src/utils/createGroqSearchFilter.ts +85 -0
- package/src/{common/util.test.ts → utils/hashString.test.ts} +1 -1
- package/dist/index.cjs +0 -4888
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -2121
- package/src/auth/fetchLoginUrls.test.ts +0 -163
- package/src/auth/fetchLoginUrls.ts +0 -74
- package/src/common/createLiveEventSubscriber.test.ts +0 -121
- package/src/common/createLiveEventSubscriber.ts +0 -55
- package/src/common/types.ts +0 -4
- package/src/instance/identity.test.ts +0 -46
- package/src/instance/identity.ts +0 -29
- package/src/instance/sanityInstance.test.ts +0 -77
- package/src/instance/sanityInstance.ts +0 -57
- package/src/instance/types.ts +0 -37
- package/src/preview/getPreviewProjection.ts +0 -45
- package/src/resources/README.md +0 -370
- package/src/resources/createAction.test.ts +0 -101
- package/src/resources/createAction.ts +0 -44
- package/src/resources/createResource.test.ts +0 -112
- package/src/resources/createResource.ts +0 -102
- package/src/resources/createStateSourceAction.test.ts +0 -114
- package/src/resources/createStateSourceAction.ts +0 -83
- package/src/resources/createStore.test.ts +0 -67
- package/src/resources/createStore.ts +0 -46
- package/src/store/createStore.test.ts +0 -108
- package/src/store/createStore.ts +0 -106
- /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:
|
|
10
|
-
doc2:
|
|
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:
|
|
22
|
-
doc2:
|
|
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:
|
|
34
|
-
|
|
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
|
-
|
|
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({
|
|
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 {
|
|
4
|
-
|
|
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]?:
|
|
25
|
+
documentProjections: {[TDocumentId in string]?: DocumentProjections},
|
|
23
26
|
): CreateProjectionQueryResult {
|
|
24
27
|
const projections = Array.from(documentIds)
|
|
25
|
-
.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return
|
|
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]?:
|
|
74
|
+
[TDocumentId in string]?: DocumentProjectionValues<Record<string, unknown>>
|
|
68
75
|
} {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
const publishedId = getPublishedId(id)
|
|
80
|
-
const draftId = getDraftId(id)
|
|
110
|
+
for (const originalId of ids) {
|
|
111
|
+
finalValues[originalId] = {}
|
|
81
112
|
|
|
82
|
-
|
|
83
|
-
|
|
113
|
+
const projectionsForDoc = groupedResults[originalId]
|
|
114
|
+
if (!projectionsForDoc) continue
|
|
84
115
|
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
...(
|
|
90
|
-
...(
|
|
127
|
+
...(draft?._updatedAt && {lastEditedDraftAt: draft._updatedAt}),
|
|
128
|
+
...(published?._updatedAt && {lastEditedPublishedAt: published._updatedAt}),
|
|
91
129
|
}
|
|
92
130
|
|
|
93
|
-
|
|
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 {
|
|
2
|
-
import {describe,
|
|
1
|
+
import {Observable} from 'rxjs'
|
|
2
|
+
import {describe, it, vi} from 'vitest'
|
|
3
3
|
|
|
4
|
-
import {createSanityInstance} from '../
|
|
5
|
-
import {
|
|
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
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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 {
|
|
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
|
|
46
|
-
|
|
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
|
})
|