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

kiva / ui / 30831419947

03 Aug 2026 04:16PM UTC coverage: 84.346% (+0.09%) from 84.257%
30831419947

push

github

emuvente
docs: guide composable data fetching and relocate SSR scope rules

Rewrite the composable data fetching docs around usage: what an author
writes, the operation options with the complete list of differences from
component blocks, and what each warning means and how to act on it. The
server rendering scope rules apply repo-wide, so they move to
docs/server-side-rendering.md with pointers from the root README and
AGENTS.md.

AD-360

6566 of 7329 branches covered (89.59%)

Branch coverage included in aggregate %.

54081 of 64574 relevant lines covered (83.75%)

28.91 hits per line

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

96.49
/src/plugins/apollo-plugin.js
1
import checkInjections from '#src/util/injectionCheck';
1✔
2
import getOperationVariables from '#src/util/operationVariables';
1✔
3
import logReadQueryError from '#src/util/logReadQueryError';
1✔
4
import watchApolloOperation from '#src/util/watchApolloOperation';
1✔
5
import { createIntersectionObserver } from '#src/util/observerUtils';
1✔
6

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

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

16
function setupWatchQuery(vm, operation, commonVars) {
22✔
17
        const { variables = () => {}, result = () => {} } = operation;
22✔
18

19
        watchApolloOperation({
22✔
20
                client: vm.apollo,
22✔
21
                operation,
22✔
22
                commonVars,
22✔
23
                getVariables: () => variables.call(vm),
22✔
24
                watchVariables: (getVariables, callback) => vm.$watch(getVariables, callback, { deep: true }),
22✔
25
                next: apolloResult => result.call(vm, apolloResult),
22✔
26
        });
22✔
27
}
22✔
28

29
// install method for plugin
1✔
30
export default app => {
1✔
31
        app.mixin({
34✔
32
                created() {
34✔
33
                        if (this.$options.apollo) {
56✔
34
                                checkInjections(this, injections);
32✔
35

36
                                // Get common variable inputs for all queries
32✔
37
                                const commonVars = { cookieStore: this.cookieStore, route: this.$route };
32✔
38

39
                                // $options.apollo is either a single object or an array of objects
32✔
40
                                const operations = Array.isArray(this.$options.apollo) ? this.$options.apollo : [this.$options.apollo];
32✔
41

42
                                this.lazyOperations = [];
32✔
43

44
                                // Load data for each query in the component
32✔
45
                                for (let i = 0; i < operations.length; i += 1) {
32✔
46
                                        const operation = operations[i];
33✔
47
                                        const {
33✔
48
                                                query,
33✔
49
                                                preFetch,
33✔
50
                                                shouldPreFetch = true,
33✔
51
                                                preFetchVariables = () => { },
33✔
52
                                                result = () => { },
33✔
53
                                        } = operation;
33✔
54

55
                                        if (query) {
33✔
56
                                                // Check if the query was prefetched
33✔
57
                                                let preFetched = preFetch && shouldPreFetch;
33✔
58
                                                if (typeof shouldPreFetch === 'function') {
33✔
59
                                                        preFetched = preFetch && shouldPreFetch(operation, {
2✔
60
                                                                cookieStore: this.cookieStore,
2✔
61
                                                                device: this.device,
2✔
62
                                                                kvAuth0: this.kvAuth0,
2✔
63
                                                                renderConfig: this.$renderConfig,
2✔
64
                                                                route: this.$route,
2✔
65
                                                        });
2✔
66
                                                }
2✔
67

68
                                                // if the query was prefetched, read the data from the cache
33✔
69
                                                if (preFetched) {
33✔
70
                                                        try {
6✔
71
                                                                const data = this.apollo.readQuery({
6✔
72
                                                                        query,
6✔
73
                                                                        variables: getOperationVariables(query, commonVars, preFetchVariables({
6✔
74
                                                                                ...commonVars,
6✔
75
                                                                                client: this.apollo,
6✔
76
                                                                        })),
6✔
77
                                                                });
6✔
78

79
                                                                if (data !== null) {
6✔
80
                                                                        result.call(this, { data });
4✔
81
                                                                }
4✔
82
                                                        } catch (e) {
6✔
83
                                                                // if there's an error, skip reading from the cache and just wait for the watch query
1✔
84
                                                                logReadQueryError(e, `ApolloMixin ${query?.definitions?.[0]?.name?.value}`);
1✔
85
                                                        }
1✔
86
                                                }
6✔
87

88
                                                const lazyConfig = parseLazy(operation.lazy);
33✔
89
                                                if (lazyConfig && !preFetched) {
33✔
90
                                                        this.lazyOperations.push({ operation, lazyConfig, commonVars });
11✔
91
                                                } else if (typeof window !== 'undefined') {
33✔
92
                                                        setupWatchQuery(this, operation, commonVars);
17✔
93
                                                }
17✔
94
                                        }
33✔
95
                                }
33✔
96
                        }
33✔
97
                },
34✔
98
                mounted() {
34✔
99
                        if (!this.lazyOperations?.length) return;
41✔
100

101
                        this.lazyObservers = [];
8✔
102

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

106
                                const { target: customTarget, ...observerOptions } = lazyConfig;
8✔
107

108
                                // Resolve the observation target: use a custom target ref if provided,
8✔
109
                                // otherwise default to this.$el. In Vue 3 fragment components, $el may
8✔
110
                                // be a comment/text node — walk siblings to find the first Element.
8✔
111
                                let target = customTarget ? this.$refs[customTarget] : this.$el;
8✔
112
                                while (target && !(target instanceof Element)) {
8!
113
                                        target = target.nextSibling;
×
114
                                }
×
115
                                if (!target) {
8!
116
                                        console.warn('[apollo-plugin] No Element found for IntersectionObserver in', this.$options.name);
×
117
                                        setupWatchQuery(this, operation, commonVars);
×
118
                                } else {
8✔
119
                                        const observer = createIntersectionObserver({
8✔
120
                                                targets: [target],
8✔
121
                                                options: observerOptions,
8✔
122
                                                callback: entries => {
8✔
123
                                                        entries.forEach(entry => {
4✔
124
                                                                if (entry.intersectionRatio > 0) {
4✔
125
                                                                        setupWatchQuery(this, operation, commonVars);
4✔
126
                                                                        observer.disconnect();
4✔
127
                                                                }
4✔
128
                                                        });
4✔
129
                                                },
8✔
130
                                        });
8✔
131

132
                                        if (observer) {
8✔
133
                                                this.lazyObservers.push(observer);
7✔
134
                                        } else {
8✔
135
                                                // IntersectionObserver not supported — fall back to immediate setup
1✔
136
                                                setupWatchQuery(this, operation, commonVars);
1✔
137
                                        }
1✔
138
                                }
8✔
139
                        }
8✔
140
                },
34✔
141
                beforeUnmount() {
34✔
142
                        if (this.lazyObservers) {
34✔
143
                                this.lazyObservers.forEach(obs => obs.disconnect());
1✔
144
                        }
1✔
145
                },
34✔
146
        });
34✔
147
};
34✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc