Skip to content

Commit 9cfa418

Browse files
authored
feat: add paused for subscriptions init object (logaretm#143)
1 parent 1aec7e7 commit 9cfa418

File tree

3 files changed

+62
-7
lines changed

3 files changed

+62
-7
lines changed

packages/villus/src/Subscription.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { defineComponent, toRef, VNode, watch } from 'vue';
2-
import { normalizeChildren } from './utils';
2+
import { normalizeChildren, CombinedError } from './utils';
33
import { useSubscription, defaultReducer, Reducer } from './useSubscription';
4-
import { CombinedError } from '../dist/villus';
54

65
interface SubscriptionSlotProps {
76
data: unknown;
@@ -36,6 +35,7 @@ const SubscriptionImpl = defineComponent({
3635
{
3736
query: props.query as string,
3837
variables: props.variables as Record<string, any> | undefined,
38+
paused: props.paused,
3939
},
4040
(props.reduce as Reducer) || defaultReducer
4141
);

packages/villus/src/useSubscription.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@ import { Operation } from '../../shared/src';
77
interface SubscriptionCompositeOptions<TData, TVars> {
88
query: MaybeRef<Operation<TData, TVars>['query']>;
99
variables?: MaybeRef<TVars>;
10+
paused?: boolean;
1011
}
1112

1213
export type Reducer<TData = any, TResult = TData> = (prev: TResult | null, value: OperationResult<TData>) => TResult;
1314

1415
export const defaultReducer: Reducer = (_, val) => val.data;
1516

1617
export function useSubscription<TData = any, TResult = TData, TVars = QueryVariables>(
17-
{ query, variables }: SubscriptionCompositeOptions<TData, TVars>,
18+
{ query, variables, paused }: SubscriptionCompositeOptions<TData, TVars>,
1819
reduce: Reducer<TData, TResult> = defaultReducer
1920
) {
2021
const client = injectWithSelf(VILLUS_CLIENT, () => {
@@ -23,7 +24,7 @@ export function useSubscription<TData = any, TResult = TData, TVars = QueryVaria
2324

2425
const data = ref<TResult | null>(reduce(null, { data: null, error: null }));
2526
const error: Ref<CombinedError | null> = ref(null);
26-
const isPaused = ref(false);
27+
const isPaused = ref(paused || false);
2728

2829
function handleResponse(result: OperationResult<TData>) {
2930
data.value = reduce(data.value as TResult, result) as any;
@@ -63,9 +64,11 @@ export function useSubscription<TData = any, TResult = TData, TVars = QueryVaria
6364
}
6465

6566
let observer: Unsubscribable;
66-
onMounted(async () => {
67-
observer = await initObserver();
68-
});
67+
if (!paused) {
68+
onMounted(async () => {
69+
observer = await initObserver();
70+
});
71+
}
6972

7073
onBeforeUnmount(() => {
7174
if (observer) {
@@ -78,6 +81,10 @@ export function useSubscription<TData = any, TResult = TData, TVars = QueryVaria
7881
}
7982

8083
async function resume() {
84+
if (!observer) {
85+
reInit();
86+
}
87+
8188
isPaused.value = false;
8289
}
8390

packages/villus/test/useSubscription.spec.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,54 @@ test('Pauses and resumes subscriptions', async () => {
240240
expect(document.querySelector('#status')?.textContent).toBe('false');
241241
});
242242

243+
test('Can pause subscriptions initially', async () => {
244+
mount({
245+
setup() {
246+
useClient({
247+
url: 'https://test.com/graphql',
248+
use: [handleSubscriptions(() => makeObservable()), ...defaultPlugins()],
249+
});
250+
251+
function reduce(oldMessages: string[] | null, response: any) {
252+
if (!response.data || !oldMessages) {
253+
return oldMessages || [];
254+
}
255+
256+
return [...oldMessages, response.data.message];
257+
}
258+
259+
const { data, resume, isPaused } = useSubscription(
260+
{ query: `subscription { newMessages }`, paused: true },
261+
reduce
262+
);
263+
264+
return { messages: data, resume, isPaused };
265+
},
266+
template: `
267+
<div>
268+
<ul v-for="message in messages">
269+
<li>{{ message.id }}</li>
270+
</ul>
271+
<button @click="resume"></button>
272+
<span id="status">{{ isPaused }}</span>
273+
</div>
274+
`,
275+
});
276+
277+
await flushPromises();
278+
jest.advanceTimersByTime(201);
279+
// pauses subscription
280+
expect(document.querySelector('#status')?.textContent).toBe('true');
281+
jest.advanceTimersByTime(201);
282+
expect(document.querySelectorAll('li')).toHaveLength(0);
283+
document.querySelector('button')?.dispatchEvent(new Event('click'));
284+
await flushPromises();
285+
expect(document.querySelector('#status')?.textContent).toBe('false');
286+
jest.advanceTimersByTime(201);
287+
await flushPromises();
288+
expect(document.querySelectorAll('li')).toHaveLength(2);
289+
});
290+
243291
test('Fails if provider was not resolved', () => {
244292
try {
245293
mount({

0 commit comments

Comments
 (0)