@sanity/sdk 0.0.0-alpha.21 → 0.0.0-alpha.23
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 +428 -325
- package/dist/index.js +1618 -1553
- package/dist/index.js.map +1 -1
- package/package.json +6 -7
- package/src/_exports/index.ts +31 -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 +9 -9
- package/src/auth/refreshStampedToken.ts +62 -56
- 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 -237
- 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 +69 -49
- package/src/projection/getProjectionState.ts +42 -50
- package/src/projection/projectionQuery.ts +1 -1
- package/src/projection/projectionStore.test.ts +13 -51
- package/src/projection/projectionStore.ts +6 -18
- package/src/projection/resolveProjection.test.ts +32 -127
- package/src/projection/resolveProjection.ts +15 -28
- package/src/projection/subscribeToStateAndFetchBatches.test.ts +105 -90
- package/src/projection/subscribeToStateAndFetchBatches.ts +94 -81
- package/src/projection/util.ts +2 -0
- 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/{common/util.test.ts → utils/hashString.test.ts} +1 -1
- 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,8 +1,13 @@
|
|
|
1
1
|
import {omit} from 'lodash-es'
|
|
2
2
|
|
|
3
|
-
import {type DocumentHandle} from '../
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import {type DocumentHandle} from '../config/sanityConfig'
|
|
4
|
+
import {bindActionByDataset} from '../store/createActionBinder'
|
|
5
|
+
import {type SanityInstance} from '../store/createSanityInstance'
|
|
6
|
+
import {
|
|
7
|
+
createStateSourceAction,
|
|
8
|
+
type SelectorContext,
|
|
9
|
+
type StateSource,
|
|
10
|
+
} from '../store/createStateSourceAction'
|
|
6
11
|
import {getPublishedId, insecureRandomId} from '../utils/ids'
|
|
7
12
|
import {
|
|
8
13
|
previewStore,
|
|
@@ -15,65 +20,72 @@ import {STABLE_EMPTY_PREVIEW} from './util'
|
|
|
15
20
|
/**
|
|
16
21
|
* @beta
|
|
17
22
|
*/
|
|
18
|
-
export
|
|
19
|
-
document: DocumentHandle
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const _getPreviewState = createStateSourceAction(
|
|
23
|
-
previewStore,
|
|
24
|
-
(state, {document}: GetPreviewStateOptions) => state.values[document._id] ?? STABLE_EMPTY_PREVIEW,
|
|
25
|
-
)
|
|
23
|
+
export type GetPreviewStateOptions = DocumentHandle
|
|
26
24
|
|
|
27
25
|
/**
|
|
28
26
|
* @beta
|
|
29
27
|
*/
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
export function getPreviewState<TResult extends object>(
|
|
29
|
+
instance: SanityInstance,
|
|
30
|
+
options: GetPreviewStateOptions,
|
|
31
|
+
): StateSource<ValuePending<TResult>>
|
|
32
|
+
/**
|
|
33
|
+
* @beta
|
|
34
|
+
*/
|
|
35
|
+
export function getPreviewState(
|
|
36
|
+
instance: SanityInstance,
|
|
37
|
+
options: GetPreviewStateOptions,
|
|
38
|
+
): StateSource<ValuePending<PreviewValue>>
|
|
39
|
+
/**
|
|
40
|
+
* @beta
|
|
41
|
+
*/
|
|
42
|
+
export function getPreviewState(
|
|
43
|
+
...args: Parameters<typeof _getPreviewState>
|
|
44
|
+
): StateSource<ValuePending<object>> {
|
|
45
|
+
return _getPreviewState(...args)
|
|
46
|
+
}
|
|
35
47
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
48
|
+
/**
|
|
49
|
+
* @beta
|
|
50
|
+
*/
|
|
51
|
+
export const _getPreviewState = bindActionByDataset(
|
|
52
|
+
previewStore,
|
|
53
|
+
createStateSourceAction({
|
|
54
|
+
selector: (
|
|
55
|
+
{state}: SelectorContext<PreviewStoreState>,
|
|
56
|
+
docHandle: GetPreviewStateOptions,
|
|
57
|
+
): ValuePending<object> => state.values[docHandle.documentId] ?? STABLE_EMPTY_PREVIEW,
|
|
58
|
+
onSubscribe: ({state}, docHandle: GetPreviewStateOptions) => {
|
|
59
|
+
const subscriptionId = insecureRandomId()
|
|
60
|
+
const documentId = getPublishedId(docHandle.documentId)
|
|
40
61
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
...prev.subscriptions,
|
|
48
|
-
[documentId]: {
|
|
49
|
-
...prev.subscriptions[documentId],
|
|
50
|
-
[subscriptionId]: true,
|
|
51
|
-
},
|
|
62
|
+
state.set('addSubscription', (prev) => ({
|
|
63
|
+
subscriptions: {
|
|
64
|
+
...prev.subscriptions,
|
|
65
|
+
[documentId]: {
|
|
66
|
+
...prev.subscriptions[documentId],
|
|
67
|
+
[subscriptionId]: true,
|
|
52
68
|
},
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const unsubscribe = previewState.subscribe(subscriber)
|
|
69
|
+
},
|
|
70
|
+
}))
|
|
56
71
|
|
|
57
|
-
|
|
58
|
-
|
|
72
|
+
return () => {
|
|
73
|
+
state.set('removeSubscription', (prev): Partial<PreviewStoreState> => {
|
|
74
|
+
const documentSubscriptions = omit(prev.subscriptions[documentId], subscriptionId)
|
|
75
|
+
const hasSubscribers = !!Object.keys(documentSubscriptions).length
|
|
76
|
+
const prevValue = prev.values[documentId]
|
|
77
|
+
const previewValue = prevValue?.data ? prevValue.data : null
|
|
59
78
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
})
|
|
79
|
+
return {
|
|
80
|
+
subscriptions: hasSubscribers
|
|
81
|
+
? {...prev.subscriptions, [documentId]: documentSubscriptions}
|
|
82
|
+
: omit(prev.subscriptions, documentId),
|
|
83
|
+
values: hasSubscribers
|
|
84
|
+
? prev.values
|
|
85
|
+
: {...prev.values, [documentId]: {data: previewValue, isPending: false}},
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
}),
|
|
91
|
+
)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fields to check for a title.
|
|
3
|
+
* The order of the items in the array defines the priority.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export const TITLE_CANDIDATES = ['title', 'name', 'label', 'heading', 'header', 'caption']
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The fields to check for a subtitle.
|
|
11
|
+
* The order of the items in the array defines the priority.
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export const SUBTITLE_CANDIDATES = ['description', 'subtitle', ...TITLE_CANDIDATES]
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Generates a GROQ projection for preview data without requiring a schema.
|
|
19
|
+
* Uses common field names to make educated guesses about which fields to use.
|
|
20
|
+
*
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
export const PREVIEW_PROJECTION = `{
|
|
24
|
+
// Get all potential title fields
|
|
25
|
+
"titleCandidates": {
|
|
26
|
+
${TITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(',\n ')}
|
|
27
|
+
},
|
|
28
|
+
// Get all potential subtitle fields
|
|
29
|
+
"subtitleCandidates": {
|
|
30
|
+
${SUBTITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(',\n ')}
|
|
31
|
+
},
|
|
32
|
+
"media": coalesce(
|
|
33
|
+
select(
|
|
34
|
+
defined(asset) => {"type": "image-asset", "_ref": asset._ref},
|
|
35
|
+
defined(image.asset) => {"type": "image-asset", "_ref": image.asset._ref},
|
|
36
|
+
defined(mainImage.asset) => {"type": "image-asset", "_ref": mainImage.asset._ref},
|
|
37
|
+
null
|
|
38
|
+
)
|
|
39
|
+
),
|
|
40
|
+
_type,
|
|
41
|
+
_id,
|
|
42
|
+
_updatedAt
|
|
43
|
+
}`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {describe, expect, it} from 'vitest'
|
|
2
2
|
|
|
3
|
-
import {SUBTITLE_CANDIDATES, TITLE_CANDIDATES} from './
|
|
3
|
+
import {SUBTITLE_CANDIDATES, TITLE_CANDIDATES} from './previewConstants'
|
|
4
4
|
import {createPreviewQuery, normalizeMedia, processPreviewQuery} from './previewQuery'
|
|
5
5
|
import {STABLE_EMPTY_PREVIEW} from './util'
|
|
6
6
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {isObject} from 'lodash-es'
|
|
2
2
|
|
|
3
|
-
import {hashString} from '../
|
|
3
|
+
import {hashString} from '../utils/hashString'
|
|
4
4
|
import {getDraftId, getPublishedId} from '../utils/ids'
|
|
5
|
-
import {
|
|
5
|
+
import {PREVIEW_PROJECTION, SUBTITLE_CANDIDATES, TITLE_CANDIDATES} from './previewConstants'
|
|
6
6
|
import {
|
|
7
7
|
type PreviewQueryResult,
|
|
8
8
|
type PreviewStoreState,
|
|
@@ -142,11 +142,10 @@ interface CreatePreviewQueryResult {
|
|
|
142
142
|
export function createPreviewQuery(documentIds: Set<string>): CreatePreviewQueryResult {
|
|
143
143
|
// Create arrays of draft and published IDs
|
|
144
144
|
const allIds = Array.from(documentIds).flatMap((id) => [getPublishedId(id), getDraftId(id)])
|
|
145
|
-
const
|
|
146
|
-
const queryHash = hashString(projection)
|
|
145
|
+
const queryHash = hashString(PREVIEW_PROJECTION)
|
|
147
146
|
|
|
148
147
|
return {
|
|
149
|
-
query: `*[_id in $__ids_${queryHash}]${
|
|
148
|
+
query: `*[_id in $__ids_${queryHash}]${PREVIEW_PROJECTION}`,
|
|
150
149
|
params: {
|
|
151
150
|
[`__ids_${queryHash}`]: allIds,
|
|
152
151
|
},
|
|
@@ -1,73 +1,28 @@
|
|
|
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 {previewStore} from './previewStore'
|
|
7
7
|
import {subscribeToStateAndFetchBatches} from './subscribeToStateAndFetchBatches'
|
|
8
|
-
import {PREVIEW_TAG} from './util'
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
vi.mock('../common/createLiveEventSubscriber', () => {
|
|
12
|
-
const mockLiveSubscriber = vi.fn()
|
|
13
|
-
return {
|
|
14
|
-
createLiveEventSubscriber: vi.fn(() => mockLiveSubscriber),
|
|
15
|
-
}
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
vi.mock('./subscribeToStateAndFetchBatches', () => ({
|
|
19
|
-
subscribeToStateAndFetchBatches: vi.fn(),
|
|
20
|
-
}))
|
|
9
|
+
vi.mock('./subscribeToStateAndFetchBatches')
|
|
21
10
|
|
|
22
11
|
describe('previewStore', () => {
|
|
23
12
|
it('is a resource that initializes with state and subscriptions', async () => {
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
documentTypes: {},
|
|
29
|
-
lastLiveEventId: null,
|
|
30
|
-
subscriptions: {},
|
|
31
|
-
syncTags: {},
|
|
32
|
-
values: {},
|
|
33
|
-
})
|
|
34
|
-
const liveUnsubscribe = vi.fn()
|
|
35
|
-
const stateUnsubscribe = vi.fn()
|
|
36
|
-
|
|
37
|
-
const {createLiveEventSubscriber} = vi.mocked(
|
|
38
|
-
await import('../common/createLiveEventSubscriber'),
|
|
13
|
+
const teardown = vi.fn()
|
|
14
|
+
const subscriber = vi.fn().mockReturnValue(teardown)
|
|
15
|
+
vi.mocked(subscribeToStateAndFetchBatches).mockReturnValue(
|
|
16
|
+
new Observable(subscriber).subscribe(),
|
|
39
17
|
)
|
|
40
|
-
const mockLiveSubscriber = vi.mocked(createLiveEventSubscriber(PREVIEW_TAG)).mockReturnValue({
|
|
41
|
-
unsubscribe: liveUnsubscribe,
|
|
42
|
-
} as unknown as Subscription)
|
|
43
18
|
|
|
44
|
-
|
|
45
|
-
unsubscribe: stateUnsubscribe,
|
|
46
|
-
}))
|
|
47
|
-
|
|
48
|
-
const dispose = previewStore.initialize!.call(
|
|
49
|
-
{
|
|
50
|
-
instance,
|
|
51
|
-
state: createResourceState(initialState),
|
|
52
|
-
},
|
|
53
|
-
instance,
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
// Verify the factory was called with the correct tag
|
|
57
|
-
expect(createLiveEventSubscriber).toHaveBeenCalledWith(PREVIEW_TAG)
|
|
19
|
+
const instance = createSanityInstance({projectId: 'p', dataset: 'd'})
|
|
58
20
|
|
|
59
|
-
|
|
60
|
-
expect(mockLiveSubscriber).toHaveBeenCalledWith({
|
|
61
|
-
instance,
|
|
62
|
-
state: expect.any(Object),
|
|
63
|
-
})
|
|
64
|
-
expect(mockLiveSubscriber).toHaveBeenCalledOnce()
|
|
21
|
+
const {state, dispose} = createStoreInstance(instance, previewStore)
|
|
65
22
|
|
|
66
|
-
expect(subscribeToStateAndFetchBatches).
|
|
23
|
+
expect(subscribeToStateAndFetchBatches).toHaveBeenCalledWith({instance, state})
|
|
67
24
|
|
|
68
25
|
dispose()
|
|
69
|
-
|
|
70
|
-
expect(liveUnsubscribe).toHaveBeenCalledOnce()
|
|
71
|
-
expect(stateUnsubscribe).toHaveBeenCalledOnce()
|
|
26
|
+
instance.dispose()
|
|
72
27
|
})
|
|
73
28
|
})
|
|
@@ -1,8 +1,5 @@
|
|
|
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 {PREVIEW_TAG} from './util'
|
|
6
3
|
|
|
7
4
|
export interface PreviewQueryResult {
|
|
8
5
|
_id: string
|
|
@@ -27,7 +24,7 @@ export interface PreviewMedia {
|
|
|
27
24
|
/**
|
|
28
25
|
* Represents the set of values displayed as a preview for a given Sanity document.
|
|
29
26
|
* This includes a primary title, a secondary subtitle, an optional piece of media associated
|
|
30
|
-
* with the document, and the document
|
|
27
|
+
* with the document, and the document's status.
|
|
31
28
|
*
|
|
32
29
|
* @public
|
|
33
30
|
*/
|
|
@@ -77,32 +74,21 @@ export type ValuePending<T> = {
|
|
|
77
74
|
/**
|
|
78
75
|
* @public
|
|
79
76
|
*/
|
|
80
|
-
export interface PreviewStoreState
|
|
77
|
+
export interface PreviewStoreState {
|
|
81
78
|
values: {[TDocumentId in string]?: ValuePending<PreviewValue>}
|
|
82
|
-
documentTypes: {[TDocumentId in string]?: string}
|
|
83
79
|
subscriptions: {[TDocumentId in string]?: {[TSubscriptionId in string]?: true}}
|
|
84
80
|
}
|
|
85
81
|
|
|
86
|
-
export const previewStore =
|
|
82
|
+
export const previewStore = defineStore<PreviewStoreState>({
|
|
87
83
|
name: 'Preview',
|
|
88
84
|
getInitialState() {
|
|
89
85
|
return {
|
|
90
|
-
documentTypes: {},
|
|
91
|
-
lastLiveEventId: null,
|
|
92
86
|
subscriptions: {},
|
|
93
|
-
syncTags: {},
|
|
94
87
|
values: {},
|
|
95
88
|
}
|
|
96
89
|
},
|
|
97
|
-
initialize() {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
const stateSubscriptionForBatches = subscribeToStateAndFetchBatches(this)
|
|
101
|
-
const liveSubscription = subscribeToLiveAndSetLastLiveEventId(this)
|
|
102
|
-
|
|
103
|
-
return () => {
|
|
104
|
-
stateSubscriptionForBatches.unsubscribe()
|
|
105
|
-
liveSubscription.unsubscribe()
|
|
106
|
-
}
|
|
90
|
+
initialize: (context) => {
|
|
91
|
+
const subscription = subscribeToStateAndFetchBatches(context)
|
|
92
|
+
return () => subscription.unsubscribe
|
|
107
93
|
},
|
|
108
94
|
})
|
|
@@ -1,119 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from '
|
|
10
|
-
import {insecureRandomId} from '../utils/ids'
|
|
11
|
-
import {
|
|
12
|
-
previewStore,
|
|
13
|
-
type PreviewStoreState,
|
|
14
|
-
type PreviewValue,
|
|
15
|
-
type ValuePending,
|
|
16
|
-
} from './previewStore'
|
|
1
|
+
import {type SanityDocumentLike} from '@sanity/types'
|
|
2
|
+
import {of} from 'rxjs'
|
|
3
|
+
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'
|
|
4
|
+
|
|
5
|
+
import {type DocumentHandle} from '../config/sanityConfig'
|
|
6
|
+
import {createSanityInstance, type SanityInstance} from '../store/createSanityInstance'
|
|
7
|
+
import {type StateSource} from '../store/createStateSourceAction'
|
|
8
|
+
import {getPreviewState} from './getPreviewState'
|
|
9
|
+
import {type PreviewValue, type ValuePending} from './previewStore'
|
|
17
10
|
import {resolvePreview} from './resolvePreview'
|
|
18
11
|
|
|
19
|
-
vi.mock('
|
|
20
|
-
const util = await importOriginal<typeof import('../utils/ids')>()
|
|
21
|
-
return {...util, insecureRandomId: vi.fn(util.insecureRandomId)}
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
vi.mock('../resources/createResource', async (importOriginal) => {
|
|
25
|
-
const original = await importOriginal<typeof import('../resources/createResource')>()
|
|
26
|
-
return {...original, getOrCreateResource: vi.fn()}
|
|
27
|
-
})
|
|
12
|
+
vi.mock('./getPreviewState')
|
|
28
13
|
|
|
29
14
|
describe('resolvePreview', () => {
|
|
30
|
-
|
|
31
|
-
const document = {_id: 'exampleId', _type: 'exampleType'}
|
|
32
|
-
const initialState: PreviewStoreState = {
|
|
33
|
-
documentTypes: {},
|
|
34
|
-
lastLiveEventId: null,
|
|
35
|
-
subscriptions: {},
|
|
36
|
-
syncTags: {},
|
|
37
|
-
values: {},
|
|
38
|
-
}
|
|
39
|
-
let state: ResourceState<PreviewStoreState>
|
|
15
|
+
let instance: SanityInstance
|
|
40
16
|
|
|
41
17
|
beforeEach(() => {
|
|
42
|
-
|
|
18
|
+
vi.resetAllMocks()
|
|
19
|
+
// Create a mock that returns the correct ValuePending type
|
|
20
|
+
vi.mocked(getPreviewState).mockReturnValue({
|
|
21
|
+
observable: of({
|
|
22
|
+
data: {title: 'test'},
|
|
23
|
+
isPending: false,
|
|
24
|
+
} as ValuePending<PreviewValue>),
|
|
25
|
+
} as StateSource<ValuePending<PreviewValue>>)
|
|
26
|
+
|
|
27
|
+
instance = createSanityInstance({projectId: 'p', dataset: 'd'})
|
|
43
28
|
})
|
|
44
29
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
;(insecureRandomId as Mock).mockImplementationOnce(() => 'pseudoRandomId')
|
|
48
|
-
|
|
49
|
-
const previewPromise = resolvePreview({state, instance}, {document})
|
|
50
|
-
expect(state.get().subscriptions).toEqual({exampleId: {pseudoRandomId: true}})
|
|
51
|
-
|
|
52
|
-
state.set('updateDifferentDocument', (prev) => ({
|
|
53
|
-
values: {
|
|
54
|
-
...prev.values,
|
|
55
|
-
differentId: {data: {title: 'Different Document'}, isPending: false},
|
|
56
|
-
},
|
|
57
|
-
}))
|
|
58
|
-
|
|
59
|
-
expect(state.get().subscriptions).toEqual({exampleId: {pseudoRandomId: true}})
|
|
60
|
-
|
|
61
|
-
state.set('updateCorrectDocumentButNull', (prev) => ({
|
|
62
|
-
values: {...prev.values, exampleId: {data: null, isPending: true}},
|
|
63
|
-
}))
|
|
64
|
-
|
|
65
|
-
expect(state.get().subscriptions).toEqual({exampleId: {pseudoRandomId: true}})
|
|
66
|
-
|
|
67
|
-
state.set('updateCorrectDocument', (prev) => ({
|
|
68
|
-
values: {...prev.values, exampleId: {data: {title: 'Correct Document'}, isPending: false}},
|
|
69
|
-
}))
|
|
70
|
-
|
|
71
|
-
const preview = await previewPromise
|
|
72
|
-
expect(preview).toEqual({data: {title: 'Correct Document'}, isPending: false})
|
|
73
|
-
|
|
74
|
-
// subscription is removed after
|
|
75
|
-
expect(state.get().subscriptions).toEqual({})
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
instance.dispose()
|
|
76
32
|
})
|
|
77
33
|
|
|
78
|
-
it('resolves
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
34
|
+
it('resolves a preview and returns the first emitted value with results', async () => {
|
|
35
|
+
const docHandle: DocumentHandle<SanityDocumentLike> = {
|
|
36
|
+
documentId: 'doc123',
|
|
37
|
+
documentType: 'movie',
|
|
82
38
|
}
|
|
83
|
-
state.set('setInitialDocument', (prev) => ({
|
|
84
|
-
values: {...prev.values, exampleId: currentValue},
|
|
85
|
-
}))
|
|
86
|
-
vi.mocked(insecureRandomId).mockImplementationOnce(() => 'pseudoRandomId')
|
|
87
|
-
expect(state.get().subscriptions).toEqual({})
|
|
88
|
-
|
|
89
|
-
const previewPromise = resolvePreview({state, instance}, {document})
|
|
90
|
-
expect(state.get().subscriptions).toEqual({exampleId: {pseudoRandomId: true}})
|
|
91
|
-
|
|
92
|
-
state.set('updateDifferentDocument', (prev) => ({
|
|
93
|
-
values: {
|
|
94
|
-
...prev.values,
|
|
95
|
-
differentId: {data: {title: 'Different Document'}, isPending: false},
|
|
96
|
-
},
|
|
97
|
-
}))
|
|
98
|
-
expect(state.get().subscriptions).toEqual({exampleId: {pseudoRandomId: true}})
|
|
99
39
|
|
|
100
|
-
|
|
101
|
-
values: {...prev.values, exampleId: currentValue},
|
|
102
|
-
}))
|
|
103
|
-
expect(state.get().subscriptions).toEqual({exampleId: {pseudoRandomId: true}})
|
|
40
|
+
const result = await resolvePreview(instance, docHandle)
|
|
104
41
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const preview = await previewPromise
|
|
111
|
-
expect(preview).toEqual({data: {title: 'New Value'}, isPending: false})
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
it('calls getOrCreateResource if no state is provided', () => {
|
|
115
|
-
vi.mocked(getOrCreateResource).mockReturnValue({state} as InitializedResource<unknown>)
|
|
116
|
-
resolvePreview(instance, {document})
|
|
117
|
-
expect(getOrCreateResource).toHaveBeenCalledWith(instance, previewStore)
|
|
42
|
+
expect(getPreviewState).toHaveBeenCalledWith(instance, docHandle)
|
|
43
|
+
expect(result).toEqual({
|
|
44
|
+
data: {title: 'test'},
|
|
45
|
+
isPending: false,
|
|
46
|
+
})
|
|
118
47
|
})
|
|
119
48
|
})
|
|
@@ -1,30 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {filter, firstValueFrom} from 'rxjs'
|
|
2
|
+
|
|
3
|
+
import {type DocumentHandle} from '../config/sanityConfig'
|
|
4
|
+
import {bindActionByDataset} from '../store/createActionBinder'
|
|
3
5
|
import {getPreviewState} from './getPreviewState'
|
|
4
|
-
import {previewStore
|
|
6
|
+
import {previewStore} from './previewStore'
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* @beta
|
|
8
10
|
*/
|
|
9
|
-
export
|
|
10
|
-
document: DocumentHandle
|
|
11
|
-
}
|
|
11
|
+
export type ResolvePreviewOptions = DocumentHandle
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* @beta
|
|
15
15
|
*/
|
|
16
|
-
export const resolvePreview =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const unsubscribe = subscribe(() => {
|
|
22
|
-
const current = getCurrent()
|
|
23
|
-
if (current?.data) {
|
|
24
|
-
resolve(current)
|
|
25
|
-
unsubscribe()
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
})
|
|
16
|
+
export const resolvePreview = bindActionByDataset(
|
|
17
|
+
previewStore,
|
|
18
|
+
({instance}, docHandle: ResolvePreviewOptions) =>
|
|
19
|
+
firstValueFrom(getPreviewState(instance, docHandle).observable.pipe(filter((i) => !!i.data))),
|
|
20
|
+
)
|