• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kiva / ui / 24354217317

13 Apr 2026 04:20PM UTC coverage: 87.062% (+0.01%) from 87.052%
24354217317

push

github

emuvente
docs(apollo): add lazy loading section to GraphQL README

4631 of 5061 branches covered (91.5%)

Branch coverage included in aggregate %.

35254 of 40751 relevant lines covered (86.51%)

41.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.6
/src/plugins/apollo-plugin.js
1
import checkInjections from '#src/util/injectionCheck';
1✔
2
import logReadQueryError from '#src/util/logReadQueryError';
1✔
3
import { isContentfulQuery } from '#src/util/contentful/isContentfulQuery';
1✔
4
import { createIntersectionObserver } from '#src/util/observerUtils';
1✔
5

6
const injections = ['apollo', 'cookieStore'];
1✔
7

8
function parseLazy(lazy) {
24✔
9
        if (!lazy) return null;
24✔
10
        if (lazy === true) return { rootMargin: '500px' };
24✔
11
        const { target, ...options } = lazy;
3✔
12
        return { rootMargin: '500px', ...options, target };
3✔
13
}
3✔
14

15
function setupWatchQuery(vm, operation, commonVars) {
13✔
16
        const {
13✔
17
                query,
13✔
18
                variables = () => {},
13✔
19
                result = () => {},
13✔
20
                fetchPolicy,
13✔
21
        } = operation;
13✔
22
        const { basketId, isContentfulPreview } = commonVars;
13✔
23

24
        const observer = vm.apollo.watchQuery({
13✔
25
                query,
13✔
26
                ...(fetchPolicy && { fetchPolicy }),
13✔
27
                variables: {
13✔
28
                        ...(basketId && { basketId }),
13✔
29
                        ...variables.call(vm),
13✔
30
                        ...(isContentfulQuery(query) && isContentfulPreview && { preview: true }),
13!
31
                },
13✔
32
        });
13✔
33

34
        vm.$watch(variables, vars => observer.setVariables({
13✔
35
                ...(basketId && { basketId }),
8!
36
                ...vars,
8✔
37
                ...(isContentfulQuery(query) && isContentfulPreview && { preview: true }),
8!
38
        }), { deep: true });
13✔
39

40
        observer.subscribe({
13✔
41
                next: apolloResult => result.call(vm, apolloResult),
13✔
42
        });
13✔
43
}
13✔
44

45
// install method for plugin
1✔
46
export default app => {
1✔
47
        app.mixin({
25✔
48
                created() {
25✔
49
                        if (this.$options.apollo) {
24✔
50
                                checkInjections(this, injections);
23✔
51

52
                                // Get common variables for all queries
23✔
53
                                const basketId = this.cookieStore?.get('kvbskt') ?? null;
23✔
54
                                const isContentfulPreview = this.$route?.query?.preview === 'true';
23✔
55

56
                                // $options.apollo is either a single object or an array of objects
23✔
57
                                const operations = Array.isArray(this.$options.apollo) ? this.$options.apollo : [this.$options.apollo];
23✔
58

59
                                this.lazyOperations = [];
23✔
60

61
                                // Load data for each query in the component
23✔
62
                                for (let i = 0; i < operations.length; i += 1) {
23✔
63
                                        const operation = operations[i];
24✔
64
                                        const {
24✔
65
                                                query,
24✔
66
                                                preFetch,
24✔
67
                                                shouldPreFetch = true,
24✔
68
                                                preFetchVariables = () => { },
24✔
69
                                                result = () => { },
24✔
70
                                        } = operation;
24✔
71

72
                                        if (query) {
24✔
73
                                                // Check if the query was prefetched
24✔
74
                                                let preFetched = preFetch && shouldPreFetch;
24✔
75
                                                if (typeof shouldPreFetch === 'function') {
24✔
76
                                                        preFetched = preFetch && shouldPreFetch(operation, {
2✔
77
                                                                cookieStore: this.cookieStore,
2✔
78
                                                                device: this.device,
2✔
79
                                                                kvAuth0: this.kvAuth0,
2✔
80
                                                                renderConfig: this.$renderConfig,
2✔
81
                                                                route: this.$route,
2✔
82
                                                        });
2✔
83
                                                }
2✔
84

85
                                                // if the query was prefetched, read the data from the cache
24✔
86
                                                if (preFetched) {
24✔
87
                                                        try {
6✔
88
                                                                const data = this.apollo.readQuery({
6✔
89
                                                                        query,
6✔
90
                                                                        variables: {
6✔
91
                                                                                ...(basketId && { basketId }),
6✔
92
                                                                                ...preFetchVariables({
6✔
93
                                                                                        cookieStore: this.cookieStore,
6✔
94
                                                                                        route: this.$route,
6✔
95
                                                                                        client: this.apollo,
6✔
96
                                                                                }),
6✔
97
                                                                                /* Adds `preview: true` variable if the query is a contentful query
6✔
98
                                                                                and the preview cookie value exists */
6✔
99
                                                                                ...(isContentfulQuery(query) && isContentfulPreview && { preview: true })
6!
100
                                                                        }
6✔
101
                                                                });
6✔
102

103
                                                                if (data !== null) {
6✔
104
                                                                        result.call(this, { data });
4✔
105
                                                                }
4✔
106
                                                        } catch (e) {
6✔
107
                                                                // if there's an error, skip reading from the cache and just wait for the watch query
1✔
108
                                                                logReadQueryError(e, `ApolloMixin ${query?.definitions?.[0]?.name?.value}`);
1✔
109
                                                        }
1✔
110
                                                }
6✔
111

112
                                                const lazyConfig = parseLazy(operation.lazy);
24✔
113
                                                const commonVars = { basketId, isContentfulPreview };
24✔
114
                                                if (lazyConfig && !preFetched) {
24✔
115
                                                        this.lazyOperations.push({ operation, lazyConfig, commonVars });
11✔
116
                                                } else if (typeof window !== 'undefined') {
24✔
117
                                                        setupWatchQuery(this, operation, commonVars);
8✔
118
                                                }
8✔
119
                                        }
24✔
120
                                }
24✔
121
                        }
24✔
122
                },
25✔
123
                mounted() {
25✔
124
                        if (!this.lazyOperations?.length) return;
9✔
125

126
                        this.lazyObservers = [];
8✔
127

128
                        for (let i = 0; i < this.lazyOperations.length; i += 1) {
8✔
129
                                const { operation, lazyConfig, commonVars } = this.lazyOperations[i];
8✔
130

131
                                const { target: customTarget, ...observerOptions } = lazyConfig;
8✔
132

133
                                // Resolve the observation target: use a custom target ref if provided,
8✔
134
                                // otherwise default to this.$el. In Vue 3 fragment components, $el may
8✔
135
                                // be a comment/text node — walk siblings to find the first Element.
8✔
136
                                let target = customTarget ? this.$refs[customTarget] : this.$el;
8✔
137
                                while (target && !(target instanceof Element)) {
8!
138
                                        target = target.nextSibling;
×
139
                                }
×
140
                                if (!target) {
8!
141
                                        console.warn('[apollo-plugin] No Element found for IntersectionObserver in', this.$options.name);
×
142
                                        setupWatchQuery(this, operation, commonVars);
×
143
                                } else {
8✔
144
                                        const observer = createIntersectionObserver({
8✔
145
                                                targets: [target],
8✔
146
                                                options: observerOptions,
8✔
147
                                                callback: entries => {
8✔
148
                                                        entries.forEach(entry => {
4✔
149
                                                                if (entry.intersectionRatio > 0) {
4✔
150
                                                                        setupWatchQuery(this, operation, commonVars);
4✔
151
                                                                        observer.disconnect();
4✔
152
                                                                }
4✔
153
                                                        });
4✔
154
                                                },
8✔
155
                                        });
8✔
156

157
                                        if (observer) {
8✔
158
                                                this.lazyObservers.push(observer);
7✔
159
                                        } else {
8✔
160
                                                // IntersectionObserver not supported — fall back to immediate setup
1✔
161
                                                setupWatchQuery(this, operation, commonVars);
1✔
162
                                        }
1✔
163
                                }
8✔
164
                        }
8✔
165
                },
25✔
166
                beforeUnmount() {
25✔
167
                        if (this.lazyObservers) {
2✔
168
                                this.lazyObservers.forEach(obs => obs.disconnect());
1✔
169
                        }
1✔
170
                },
25✔
171
        });
25✔
172
};
25✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc