houdini 1.1.3 → 1.1.4-react.0

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.
Files changed (41) hide show
  1. package/build/cmd-cjs/index.js +230 -158
  2. package/build/cmd-esm/index.js +230 -158
  3. package/build/codegen-cjs/index.js +217 -156
  4. package/build/codegen-esm/index.js +217 -156
  5. package/build/lib/config.d.ts +1 -0
  6. package/build/lib/parse.d.ts +2 -1
  7. package/build/lib/types.d.ts +4 -1
  8. package/build/lib-cjs/index.js +178 -146
  9. package/build/lib-esm/index.js +178 -146
  10. package/build/runtime/client/documentStore.d.ts +3 -0
  11. package/build/runtime/client/index.d.ts +1 -1
  12. package/build/runtime/lib/pageInfo.d.ts +7 -0
  13. package/build/runtime/lib/pagination.d.ts +29 -0
  14. package/build/runtime/lib/types.d.ts +46 -0
  15. package/build/runtime-cjs/client/documentStore.d.ts +3 -0
  16. package/build/runtime-cjs/client/documentStore.js +11 -6
  17. package/build/runtime-cjs/client/index.d.ts +1 -1
  18. package/build/runtime-cjs/client/plugins/cache.js +6 -3
  19. package/build/runtime-cjs/client/plugins/fragment.js +8 -1
  20. package/build/runtime-cjs/client/plugins/query.js +2 -1
  21. package/build/runtime-cjs/lib/pageInfo.d.ts +7 -0
  22. package/build/runtime-cjs/lib/pageInfo.js +79 -0
  23. package/build/runtime-cjs/lib/pagination.d.ts +29 -0
  24. package/build/runtime-cjs/lib/pagination.js +231 -0
  25. package/build/runtime-cjs/lib/types.d.ts +46 -0
  26. package/build/runtime-esm/client/documentStore.d.ts +3 -0
  27. package/build/runtime-esm/client/documentStore.js +11 -6
  28. package/build/runtime-esm/client/index.d.ts +1 -1
  29. package/build/runtime-esm/client/plugins/cache.js +6 -3
  30. package/build/runtime-esm/client/plugins/fragment.js +8 -1
  31. package/build/runtime-esm/client/plugins/query.js +2 -1
  32. package/build/runtime-esm/lib/pageInfo.d.ts +7 -0
  33. package/build/runtime-esm/lib/pageInfo.js +52 -0
  34. package/build/runtime-esm/lib/pagination.d.ts +29 -0
  35. package/build/runtime-esm/lib/pagination.js +206 -0
  36. package/build/runtime-esm/lib/types.d.ts +46 -0
  37. package/build/test-cjs/index.js +224 -155
  38. package/build/test-esm/index.js +224 -155
  39. package/build/vite-cjs/index.js +228 -156
  40. package/build/vite-esm/index.js +228 -156
  41. package/package.json +1 -1
@@ -0,0 +1,52 @@
1
+ import { siteURL } from "./constants";
2
+ function nullPageInfo() {
3
+ return { startCursor: null, endCursor: null, hasNextPage: false, hasPreviousPage: false };
4
+ }
5
+ function missingPageSizeError(fnName) {
6
+ return {
7
+ message: `${fnName} is missing the required page arguments. For more information, please visit this link: ${siteURL}/guides/pagination`
8
+ };
9
+ }
10
+ function extractPageInfo(data, path) {
11
+ if (!data) {
12
+ return {
13
+ startCursor: null,
14
+ endCursor: null,
15
+ hasNextPage: false,
16
+ hasPreviousPage: false
17
+ };
18
+ }
19
+ let localPath = [...path];
20
+ let current = data;
21
+ while (localPath.length > 0) {
22
+ if (!current) {
23
+ break;
24
+ }
25
+ current = current[localPath.shift()];
26
+ }
27
+ return current?.pageInfo ?? nullPageInfo();
28
+ }
29
+ function countPage(source, value) {
30
+ let data = value;
31
+ if (value === null || data === null || data === void 0) {
32
+ return 0;
33
+ }
34
+ for (const field of source) {
35
+ const obj = data[field];
36
+ if (obj && !Array.isArray(obj)) {
37
+ data = obj;
38
+ } else if (!data) {
39
+ throw new Error("Could not count page size");
40
+ }
41
+ if (Array.isArray(obj)) {
42
+ return obj.length;
43
+ }
44
+ }
45
+ return 0;
46
+ }
47
+ export {
48
+ countPage,
49
+ extractPageInfo,
50
+ missingPageSizeError,
51
+ nullPageInfo
52
+ };
@@ -0,0 +1,29 @@
1
+ import type { SendParams } from '../client/documentStore';
2
+ import { FetchParams } from './types';
3
+ import type { CursorHandlers, FetchFn, GraphQLObject, QueryArtifact, QueryResult } from './types';
4
+ export declare function cursorHandlers<_Data extends GraphQLObject, _Input extends Record<string, any>>({ artifact, storeName, fetchUpdate: parentFetchUpdate, fetch: parentFetch, getState, getVariables, getSession, }: {
5
+ artifact: QueryArtifact;
6
+ storeName: string;
7
+ getState: () => _Data | null;
8
+ getVariables: () => _Input;
9
+ getSession: () => Promise<App.Session>;
10
+ fetch: FetchFn<_Data, _Input>;
11
+ fetchUpdate: (arg: SendParams, updates: string[]) => ReturnType<FetchFn<_Data, _Input>>;
12
+ }): CursorHandlers<_Data, _Input>;
13
+ export declare function offsetHandlers<_Data extends GraphQLObject, _Input extends {}>({ artifact, storeName, getState, getVariables, fetch: parentFetch, fetchUpdate: parentFetchUpdate, getSession, }: {
14
+ artifact: QueryArtifact;
15
+ fetch: FetchFn<_Data, _Input>;
16
+ fetchUpdate: (arg: SendParams) => ReturnType<FetchFn<_Data, _Input>>;
17
+ storeName: string;
18
+ getState: () => _Data | null;
19
+ getVariables: () => _Input;
20
+ getSession: () => Promise<App.Session>;
21
+ }): {
22
+ loadNextPage: ({ limit, offset, fetch, metadata, }?: {
23
+ limit?: number | undefined;
24
+ offset?: number | undefined;
25
+ fetch?: typeof fetch | undefined;
26
+ metadata?: {} | undefined;
27
+ }) => Promise<void>;
28
+ fetch(params?: FetchParams<_Input>): Promise<QueryResult<_Data, _Input>>;
29
+ };
@@ -0,0 +1,206 @@
1
+ import { getCurrentConfig } from "./config";
2
+ import { siteURL } from "./constants";
3
+ import { deepEquals } from "./deepEquals";
4
+ import { countPage, extractPageInfo, missingPageSizeError } from "./pageInfo";
5
+ import { CachePolicy } from "./types";
6
+ function cursorHandlers({
7
+ artifact,
8
+ storeName,
9
+ fetchUpdate: parentFetchUpdate,
10
+ fetch: parentFetch,
11
+ getState,
12
+ getVariables,
13
+ getSession
14
+ }) {
15
+ const loadPage = async ({
16
+ pageSizeVar,
17
+ input,
18
+ functionName,
19
+ metadata = {},
20
+ fetch,
21
+ where
22
+ }) => {
23
+ const config = getCurrentConfig();
24
+ const loadVariables = {
25
+ ...getVariables(),
26
+ ...input
27
+ };
28
+ if (!loadVariables[pageSizeVar] && !artifact.refetch.pageSize) {
29
+ throw missingPageSizeError(functionName);
30
+ }
31
+ let isSinglePage = artifact.refetch?.mode === "SinglePage";
32
+ await (isSinglePage ? parentFetch : parentFetchUpdate)(
33
+ {
34
+ variables: loadVariables,
35
+ fetch,
36
+ metadata,
37
+ policy: isSinglePage ? artifact.policy : CachePolicy.NetworkOnly,
38
+ session: await getSession()
39
+ },
40
+ isSinglePage ? [] : [where === "start" ? "prepend" : "append"]
41
+ );
42
+ const resultPath = [...artifact.refetch.path];
43
+ if (artifact.refetch.embedded) {
44
+ const { targetType } = artifact.refetch;
45
+ if (!config.types?.[targetType]?.resolve) {
46
+ throw new Error(
47
+ `Missing type resolve configuration for ${targetType}. For more information, see ${siteURL}/guides/pagination#paginated-fragments`
48
+ );
49
+ }
50
+ resultPath.unshift(config.types[targetType].resolve.queryField);
51
+ }
52
+ };
53
+ const getPageInfo = () => {
54
+ return extractPageInfo(getState(), artifact.refetch?.path ?? []);
55
+ };
56
+ return {
57
+ loadNextPage: async ({
58
+ first,
59
+ after,
60
+ fetch,
61
+ metadata
62
+ } = {}) => {
63
+ const currentPageInfo = getPageInfo();
64
+ if (!currentPageInfo.hasNextPage) {
65
+ return;
66
+ }
67
+ const input = {
68
+ first: first ?? artifact.refetch.pageSize,
69
+ after: after ?? currentPageInfo.endCursor,
70
+ before: null,
71
+ last: null
72
+ };
73
+ return await loadPage({
74
+ pageSizeVar: "first",
75
+ functionName: "loadNextPage",
76
+ input,
77
+ fetch,
78
+ metadata,
79
+ where: "end"
80
+ });
81
+ },
82
+ loadPreviousPage: async ({
83
+ last,
84
+ before,
85
+ fetch,
86
+ metadata
87
+ } = {}) => {
88
+ const currentPageInfo = getPageInfo();
89
+ if (!currentPageInfo.hasPreviousPage) {
90
+ return;
91
+ }
92
+ const input = {
93
+ before: before ?? currentPageInfo.startCursor,
94
+ last: last ?? artifact.refetch.pageSize,
95
+ first: null,
96
+ after: null
97
+ };
98
+ return await loadPage({
99
+ pageSizeVar: "last",
100
+ functionName: "loadPreviousPage",
101
+ input,
102
+ fetch,
103
+ metadata,
104
+ where: "start"
105
+ });
106
+ },
107
+ async fetch(args) {
108
+ const { variables } = args ?? {};
109
+ if (variables && !deepEquals(getVariables(), variables)) {
110
+ return await parentFetch(args);
111
+ }
112
+ try {
113
+ var currentPageInfo = extractPageInfo(getState(), artifact.refetch.path);
114
+ } catch {
115
+ return await parentFetch(args);
116
+ }
117
+ const queryVariables = {};
118
+ const count = countPage(artifact.refetch.path.concat("edges"), getState()) || artifact.refetch.pageSize;
119
+ if (count && count > artifact.refetch.pageSize) {
120
+ if (currentPageInfo.hasPreviousPage && currentPageInfo.hasNextPage && !(variables?.["first"] && variables?.["after"] || variables?.["last"] && variables?.["before"])) {
121
+ console.warn(`\u26A0\uFE0F Encountered a fetch() in the middle of the connection.
122
+ Make sure to pass a cursor value by hand that includes the current set (ie the entry before startCursor)
123
+ `);
124
+ }
125
+ if (!currentPageInfo.hasPreviousPage) {
126
+ queryVariables["first"] = count;
127
+ queryVariables["after"] = null;
128
+ queryVariables["last"] = null;
129
+ queryVariables["before"] = null;
130
+ } else if (!currentPageInfo.hasNextPage) {
131
+ queryVariables["last"] = count;
132
+ queryVariables["first"] = null;
133
+ queryVariables["after"] = null;
134
+ queryVariables["before"] = null;
135
+ }
136
+ }
137
+ Object.assign(queryVariables, variables ?? {});
138
+ const result = await parentFetch({
139
+ ...args,
140
+ variables: queryVariables
141
+ });
142
+ return result;
143
+ }
144
+ };
145
+ }
146
+ function offsetHandlers({
147
+ artifact,
148
+ storeName,
149
+ getState,
150
+ getVariables,
151
+ fetch: parentFetch,
152
+ fetchUpdate: parentFetchUpdate,
153
+ getSession
154
+ }) {
155
+ let getOffset = () => artifact.refetch?.start || countPage(artifact.refetch.path, getState()) || artifact.refetch.pageSize;
156
+ let currentOffset = getOffset() ?? 0;
157
+ return {
158
+ loadNextPage: async ({
159
+ limit,
160
+ offset,
161
+ fetch,
162
+ metadata
163
+ } = {}) => {
164
+ const queryVariables = {
165
+ ...getVariables(),
166
+ offset: offset ?? getOffset()
167
+ };
168
+ if (limit || limit === 0) {
169
+ queryVariables.limit = limit;
170
+ }
171
+ if (!queryVariables.limit && !artifact.refetch.pageSize) {
172
+ throw missingPageSizeError("loadNextPage");
173
+ }
174
+ let isSinglePage = artifact.refetch?.mode === "SinglePage";
175
+ const targetFetch = isSinglePage ? parentFetch : parentFetchUpdate;
176
+ await targetFetch({
177
+ variables: queryVariables,
178
+ fetch,
179
+ metadata,
180
+ policy: isSinglePage ? artifact.policy : CachePolicy.NetworkOnly,
181
+ session: await getSession()
182
+ });
183
+ const pageSize = queryVariables.limit || artifact.refetch.pageSize;
184
+ currentOffset = offset + pageSize;
185
+ },
186
+ async fetch(params = {}) {
187
+ const { variables } = params;
188
+ if (variables && !deepEquals(getVariables(), variables)) {
189
+ return parentFetch.call(this, params);
190
+ }
191
+ const count = currentOffset || getOffset();
192
+ const queryVariables = {};
193
+ if (!artifact.refetch.pageSize || count > artifact.refetch.pageSize) {
194
+ queryVariables.limit = count;
195
+ }
196
+ return await parentFetch.call(this, {
197
+ ...params,
198
+ variables: queryVariables
199
+ });
200
+ }
201
+ };
202
+ }
203
+ export {
204
+ cursorHandlers,
205
+ offsetHandlers
206
+ };
@@ -25,6 +25,7 @@ declare global {
25
25
  };
26
26
  optimisticResponse?: GraphQLObject;
27
27
  parentID?: string;
28
+ silenceLoading?: boolean;
28
29
  }
29
30
  }
30
31
  }
@@ -193,6 +194,51 @@ export type ValueOf<Parent> = Parent[keyof Parent];
193
194
  export declare const fragmentKey = " $fragments";
194
195
  export type ValueNode = VariableNode | IntValueNode | FloatValueNode | StringValueNode | BooleanValueNode | NullValueNode | EnumValueNode | ListValueNode | ObjectValueNode;
195
196
  export type ValueMap = Record<string, ValueNode>;
197
+ export type FetchParams<_Input> = {
198
+ variables?: _Input;
199
+ /**
200
+ * The policy to use when performing the fetch. If set to CachePolicy.NetworkOnly,
201
+ * a request will always be sent, even if the variables are the same as the last call
202
+ * to fetch.
203
+ */
204
+ policy?: CachePolicies;
205
+ /**
206
+ * An object that will be passed to the fetch function.
207
+ * You can do what you want with it!
208
+ */
209
+ metadata?: App.Metadata;
210
+ };
211
+ export type FetchFn<_Data extends GraphQLObject, _Input = any> = (params?: FetchParams<_Input>) => Promise<QueryResult<_Data, _Input>>;
212
+ export type CursorHandlers<_Data extends GraphQLObject, _Input> = {
213
+ loadNextPage: (args?: {
214
+ first?: number;
215
+ after?: string;
216
+ fetch?: typeof globalThis.fetch;
217
+ metadata?: {};
218
+ }) => Promise<void>;
219
+ loadPreviousPage: (args?: {
220
+ last?: number;
221
+ before?: string;
222
+ fetch?: typeof globalThis.fetch;
223
+ metadata?: {};
224
+ }) => Promise<void>;
225
+ fetch(args?: FetchParams<_Input> | undefined): Promise<QueryResult<_Data, _Input>>;
226
+ };
227
+ export type OffsetHandlers<_Data extends GraphQLObject, _Input> = {
228
+ loadNextPage: (args?: {
229
+ limit?: number;
230
+ offset?: number;
231
+ metadata?: {};
232
+ fetch?: typeof globalThis.fetch;
233
+ }) => Promise<void>;
234
+ fetch(args?: FetchParams<_Input> | undefined): Promise<QueryResult<_Data, _Input>>;
235
+ };
236
+ export type PageInfo = {
237
+ startCursor: string | null;
238
+ endCursor: string | null;
239
+ hasNextPage: boolean;
240
+ hasPreviousPage: boolean;
241
+ };
196
242
  interface IntValueNode {
197
243
  readonly kind: 'IntValue';
198
244
  readonly value: string;