-
Notifications
You must be signed in to change notification settings - Fork 12
/
previewSubscriptionStore.ts
126 lines (111 loc) · 3.21 KB
/
previewSubscriptionStore.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import type { GroqStore, Subscription } from '@sanity/groq-store';
import { type Aborter, getAborter } from './aborter';
import type { Params, ProjectConfig, SubscriptionOptions } from './types';
import { get, writable } from 'svelte/store';
import { getCurrentUser } from './currentUser';
import { onMount } from 'svelte';
const EMPTY_PARAMS = {};
export function createPreviewSubscriptionStore({
projectId,
dataset,
token,
EventSource,
documentLimit = 3000,
}: ProjectConfig & { documentLimit?: number }) {
// Only construct/setup the store when `getStore()` is called
let store: Promise<GroqStore>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return function previewSubscriptionStore<R = any>(query: string, options: SubscriptionOptions<R> = {}) {
const { params = EMPTY_PARAMS, initialData, enabled } = options;
return querySubscription<R>({
getStore,
projectId,
query,
params,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
initialData: initialData as any,
enabled: enabled ? typeof window !== 'undefined' : false,
token,
});
};
function getStore(abort: Aborter) {
if (!store) {
store = import('@sanity/groq-store').then(({ groqStore }) => {
// Skip creating the groq store if we've been unmounted to save memory and reduce gc pressure
if (abort.signal.aborted) {
const error = new Error('Cancelling groq store creation');
// This ensures we can skip it in the catch block same way
error.name = 'AbortError';
return Promise.reject(error);
}
return groqStore({
projectId,
dataset,
documentLimit,
token,
EventSource,
listen: true,
overlayDrafts: true,
subscriptionThrottleMs: 10,
});
});
}
return store;
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function querySubscription<R = any>(options: {
getStore: (abort: Aborter) => Promise<GroqStore>;
projectId: string;
query: string;
params: Params;
initialData: R;
enabled: boolean;
token?: string;
}) {
const { getStore, projectId, query, initialData, enabled = false, token } = options;
const error = writable<Error>();
const loading = writable(false);
const data = writable<R>();
const params = writable<Params>(options.params);
onMount(() => {
if (!enabled) {
return;
}
loading.set(true);
const aborter = getAborter();
let subscription: Subscription | undefined;
getCurrentUser(projectId, aborter, token)
.then((user) => {
if (user) {
return;
}
// eslint-disable-next-line no-console
console.warn('Not authenticated - preview not available');
throw new Error('Not authenticated - preview not available');
})
.then(() => getStore(aborter))
.then((store) => {
subscription = store.subscribe(query, get(params), (err, result) => {
if (err) {
error.set(err);
} else {
data.set(result);
}
});
})
.catch((err: Error) => (err.name === 'AbortError' ? null : error.set(err)))
.finally(() => loading.set(false));
return () => {
if (subscription) {
subscription.unsubscribe();
}
aborter.abort();
};
});
return {
data: typeof get(data) === 'undefined' ? writable(initialData) : data,
error,
loading,
};
}