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.
- package/build/cmd-cjs/index.js +230 -158
- package/build/cmd-esm/index.js +230 -158
- package/build/codegen-cjs/index.js +217 -156
- package/build/codegen-esm/index.js +217 -156
- package/build/lib/config.d.ts +1 -0
- package/build/lib/parse.d.ts +2 -1
- package/build/lib/types.d.ts +4 -1
- package/build/lib-cjs/index.js +178 -146
- package/build/lib-esm/index.js +178 -146
- package/build/runtime/client/documentStore.d.ts +3 -0
- package/build/runtime/client/index.d.ts +1 -1
- package/build/runtime/lib/pageInfo.d.ts +7 -0
- package/build/runtime/lib/pagination.d.ts +29 -0
- package/build/runtime/lib/types.d.ts +46 -0
- package/build/runtime-cjs/client/documentStore.d.ts +3 -0
- package/build/runtime-cjs/client/documentStore.js +11 -6
- package/build/runtime-cjs/client/index.d.ts +1 -1
- package/build/runtime-cjs/client/plugins/cache.js +6 -3
- package/build/runtime-cjs/client/plugins/fragment.js +8 -1
- package/build/runtime-cjs/client/plugins/query.js +2 -1
- package/build/runtime-cjs/lib/pageInfo.d.ts +7 -0
- package/build/runtime-cjs/lib/pageInfo.js +79 -0
- package/build/runtime-cjs/lib/pagination.d.ts +29 -0
- package/build/runtime-cjs/lib/pagination.js +231 -0
- package/build/runtime-cjs/lib/types.d.ts +46 -0
- package/build/runtime-esm/client/documentStore.d.ts +3 -0
- package/build/runtime-esm/client/documentStore.js +11 -6
- package/build/runtime-esm/client/index.d.ts +1 -1
- package/build/runtime-esm/client/plugins/cache.js +6 -3
- package/build/runtime-esm/client/plugins/fragment.js +8 -1
- package/build/runtime-esm/client/plugins/query.js +2 -1
- package/build/runtime-esm/lib/pageInfo.d.ts +7 -0
- package/build/runtime-esm/lib/pageInfo.js +52 -0
- package/build/runtime-esm/lib/pagination.d.ts +29 -0
- package/build/runtime-esm/lib/pagination.js +206 -0
- package/build/runtime-esm/lib/types.d.ts +46 -0
- package/build/test-cjs/index.js +224 -155
- package/build/test-esm/index.js +224 -155
- package/build/vite-cjs/index.js +228 -156
- package/build/vite-esm/index.js +228 -156
- package/package.json +1 -1
|
@@ -41,11 +41,12 @@ const cachePolicy = ({
|
|
|
41
41
|
network(ctx, { initialValue, next, resolve, marshalVariables }) {
|
|
42
42
|
const { policy, artifact } = ctx;
|
|
43
43
|
let useCache = false;
|
|
44
|
-
if (enabled && artifact.kind === import_types.ArtifactKind.Query && !ctx.cacheParams?.disableRead) {
|
|
44
|
+
if (enabled && (artifact.kind === import_types.ArtifactKind.Query || artifact.kind === import_types.ArtifactKind.Fragment) && !ctx.cacheParams?.disableRead) {
|
|
45
45
|
if (policy !== import_types.CachePolicy.NetworkOnly) {
|
|
46
46
|
const value = localCache.read({
|
|
47
47
|
selection: artifact.selection,
|
|
48
|
-
variables: marshalVariables(ctx)
|
|
48
|
+
variables: marshalVariables(ctx),
|
|
49
|
+
parent: ctx.stuff?.parentID
|
|
49
50
|
});
|
|
50
51
|
const allowed = !value.partial || artifact.kind === import_types.ArtifactKind.Query && artifact.partial;
|
|
51
52
|
if (policy === import_types.CachePolicy.CacheOnly) {
|
|
@@ -81,7 +82,9 @@ const cachePolicy = ({
|
|
|
81
82
|
localCache._internal_unstable.collectGarbage();
|
|
82
83
|
}, 0);
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
+
if (!ctx.stuff?.silenceLoading) {
|
|
86
|
+
setFetching(!useCache);
|
|
87
|
+
}
|
|
85
88
|
return next(ctx);
|
|
86
89
|
},
|
|
87
90
|
afterNetwork(ctx, { resolve, value, marshalVariables }) {
|
|
@@ -28,16 +28,22 @@ __export(fragment_exports, {
|
|
|
28
28
|
});
|
|
29
29
|
module.exports = __toCommonJS(fragment_exports);
|
|
30
30
|
var import_cache = __toESM(require("../../cache"), 1);
|
|
31
|
+
var import_deepEquals = require("../../lib/deepEquals");
|
|
31
32
|
var import_types = require("../../lib/types");
|
|
32
33
|
var import_utils = require("../utils");
|
|
33
34
|
const fragment = (0, import_utils.documentPlugin)(import_types.ArtifactKind.Fragment, function() {
|
|
34
35
|
let subscriptionSpec = null;
|
|
36
|
+
let lastReference = null;
|
|
35
37
|
return {
|
|
36
38
|
start(ctx, { next, resolve, variablesChanged, marshalVariables }) {
|
|
37
39
|
if (!ctx.stuff.parentID) {
|
|
38
40
|
return next(ctx);
|
|
39
41
|
}
|
|
40
|
-
|
|
42
|
+
const currentReference = {
|
|
43
|
+
parent: ctx.stuff.parentID,
|
|
44
|
+
variables: marshalVariables(ctx)
|
|
45
|
+
};
|
|
46
|
+
if (!ctx.cacheParams?.disableSubscriptions && (!(0, import_deepEquals.deepEquals)(lastReference, currentReference) || variablesChanged(ctx))) {
|
|
41
47
|
if (subscriptionSpec) {
|
|
42
48
|
import_cache.default.unsubscribe(subscriptionSpec, subscriptionSpec.variables?.() || {});
|
|
43
49
|
}
|
|
@@ -60,6 +66,7 @@ const fragment = (0, import_utils.documentPlugin)(import_types.ArtifactKind.Frag
|
|
|
60
66
|
}
|
|
61
67
|
};
|
|
62
68
|
import_cache.default.subscribe(subscriptionSpec, variables);
|
|
69
|
+
lastReference = currentReference;
|
|
63
70
|
}
|
|
64
71
|
next(ctx);
|
|
65
72
|
},
|
|
@@ -47,10 +47,11 @@ const query = (0, import_utils.documentPlugin)(import_types.ArtifactKind.Query,
|
|
|
47
47
|
import_cache.default.unsubscribe(subscriptionSpec, subscriptionSpec.variables?.() || {});
|
|
48
48
|
}
|
|
49
49
|
lastVariables = { ...marshalVariables(ctx) };
|
|
50
|
+
const variables = lastVariables;
|
|
50
51
|
subscriptionSpec = {
|
|
51
52
|
rootType: ctx.artifact.rootType,
|
|
52
53
|
selection: ctx.artifact.selection,
|
|
53
|
-
variables: () =>
|
|
54
|
+
variables: () => variables,
|
|
54
55
|
set: (newValue) => {
|
|
55
56
|
resolve(ctx, {
|
|
56
57
|
data: newValue,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { GraphQLObject, PageInfo } from './types';
|
|
2
|
+
export declare function nullPageInfo(): PageInfo;
|
|
3
|
+
export declare function missingPageSizeError(fnName: string): {
|
|
4
|
+
message: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function extractPageInfo(data: any, path: string[]): PageInfo;
|
|
7
|
+
export declare function countPage<_Data extends GraphQLObject>(source: string[], value: _Data | null): number;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var pageInfo_exports = {};
|
|
20
|
+
__export(pageInfo_exports, {
|
|
21
|
+
countPage: () => countPage,
|
|
22
|
+
extractPageInfo: () => extractPageInfo,
|
|
23
|
+
missingPageSizeError: () => missingPageSizeError,
|
|
24
|
+
nullPageInfo: () => nullPageInfo
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(pageInfo_exports);
|
|
27
|
+
var import_constants = require("./constants");
|
|
28
|
+
function nullPageInfo() {
|
|
29
|
+
return { startCursor: null, endCursor: null, hasNextPage: false, hasPreviousPage: false };
|
|
30
|
+
}
|
|
31
|
+
function missingPageSizeError(fnName) {
|
|
32
|
+
return {
|
|
33
|
+
message: `${fnName} is missing the required page arguments. For more information, please visit this link: ${import_constants.siteURL}/guides/pagination`
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function extractPageInfo(data, path) {
|
|
37
|
+
if (!data) {
|
|
38
|
+
return {
|
|
39
|
+
startCursor: null,
|
|
40
|
+
endCursor: null,
|
|
41
|
+
hasNextPage: false,
|
|
42
|
+
hasPreviousPage: false
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
let localPath = [...path];
|
|
46
|
+
let current = data;
|
|
47
|
+
while (localPath.length > 0) {
|
|
48
|
+
if (!current) {
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
current = current[localPath.shift()];
|
|
52
|
+
}
|
|
53
|
+
return current?.pageInfo ?? nullPageInfo();
|
|
54
|
+
}
|
|
55
|
+
function countPage(source, value) {
|
|
56
|
+
let data = value;
|
|
57
|
+
if (value === null || data === null || data === void 0) {
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
for (const field of source) {
|
|
61
|
+
const obj = data[field];
|
|
62
|
+
if (obj && !Array.isArray(obj)) {
|
|
63
|
+
data = obj;
|
|
64
|
+
} else if (!data) {
|
|
65
|
+
throw new Error("Could not count page size");
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(obj)) {
|
|
68
|
+
return obj.length;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
74
|
+
0 && (module.exports = {
|
|
75
|
+
countPage,
|
|
76
|
+
extractPageInfo,
|
|
77
|
+
missingPageSizeError,
|
|
78
|
+
nullPageInfo
|
|
79
|
+
});
|
|
@@ -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,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var pagination_exports = {};
|
|
20
|
+
__export(pagination_exports, {
|
|
21
|
+
cursorHandlers: () => cursorHandlers,
|
|
22
|
+
offsetHandlers: () => offsetHandlers
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(pagination_exports);
|
|
25
|
+
var import_config = require("./config");
|
|
26
|
+
var import_constants = require("./constants");
|
|
27
|
+
var import_deepEquals = require("./deepEquals");
|
|
28
|
+
var import_pageInfo = require("./pageInfo");
|
|
29
|
+
var import_types = require("./types");
|
|
30
|
+
function cursorHandlers({
|
|
31
|
+
artifact,
|
|
32
|
+
storeName,
|
|
33
|
+
fetchUpdate: parentFetchUpdate,
|
|
34
|
+
fetch: parentFetch,
|
|
35
|
+
getState,
|
|
36
|
+
getVariables,
|
|
37
|
+
getSession
|
|
38
|
+
}) {
|
|
39
|
+
const loadPage = async ({
|
|
40
|
+
pageSizeVar,
|
|
41
|
+
input,
|
|
42
|
+
functionName,
|
|
43
|
+
metadata = {},
|
|
44
|
+
fetch,
|
|
45
|
+
where
|
|
46
|
+
}) => {
|
|
47
|
+
const config = (0, import_config.getCurrentConfig)();
|
|
48
|
+
const loadVariables = {
|
|
49
|
+
...getVariables(),
|
|
50
|
+
...input
|
|
51
|
+
};
|
|
52
|
+
if (!loadVariables[pageSizeVar] && !artifact.refetch.pageSize) {
|
|
53
|
+
throw (0, import_pageInfo.missingPageSizeError)(functionName);
|
|
54
|
+
}
|
|
55
|
+
let isSinglePage = artifact.refetch?.mode === "SinglePage";
|
|
56
|
+
await (isSinglePage ? parentFetch : parentFetchUpdate)(
|
|
57
|
+
{
|
|
58
|
+
variables: loadVariables,
|
|
59
|
+
fetch,
|
|
60
|
+
metadata,
|
|
61
|
+
policy: isSinglePage ? artifact.policy : import_types.CachePolicy.NetworkOnly,
|
|
62
|
+
session: await getSession()
|
|
63
|
+
},
|
|
64
|
+
isSinglePage ? [] : [where === "start" ? "prepend" : "append"]
|
|
65
|
+
);
|
|
66
|
+
const resultPath = [...artifact.refetch.path];
|
|
67
|
+
if (artifact.refetch.embedded) {
|
|
68
|
+
const { targetType } = artifact.refetch;
|
|
69
|
+
if (!config.types?.[targetType]?.resolve) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Missing type resolve configuration for ${targetType}. For more information, see ${import_constants.siteURL}/guides/pagination#paginated-fragments`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
resultPath.unshift(config.types[targetType].resolve.queryField);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const getPageInfo = () => {
|
|
78
|
+
return (0, import_pageInfo.extractPageInfo)(getState(), artifact.refetch?.path ?? []);
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
loadNextPage: async ({
|
|
82
|
+
first,
|
|
83
|
+
after,
|
|
84
|
+
fetch,
|
|
85
|
+
metadata
|
|
86
|
+
} = {}) => {
|
|
87
|
+
const currentPageInfo = getPageInfo();
|
|
88
|
+
if (!currentPageInfo.hasNextPage) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const input = {
|
|
92
|
+
first: first ?? artifact.refetch.pageSize,
|
|
93
|
+
after: after ?? currentPageInfo.endCursor,
|
|
94
|
+
before: null,
|
|
95
|
+
last: null
|
|
96
|
+
};
|
|
97
|
+
return await loadPage({
|
|
98
|
+
pageSizeVar: "first",
|
|
99
|
+
functionName: "loadNextPage",
|
|
100
|
+
input,
|
|
101
|
+
fetch,
|
|
102
|
+
metadata,
|
|
103
|
+
where: "end"
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
loadPreviousPage: async ({
|
|
107
|
+
last,
|
|
108
|
+
before,
|
|
109
|
+
fetch,
|
|
110
|
+
metadata
|
|
111
|
+
} = {}) => {
|
|
112
|
+
const currentPageInfo = getPageInfo();
|
|
113
|
+
if (!currentPageInfo.hasPreviousPage) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const input = {
|
|
117
|
+
before: before ?? currentPageInfo.startCursor,
|
|
118
|
+
last: last ?? artifact.refetch.pageSize,
|
|
119
|
+
first: null,
|
|
120
|
+
after: null
|
|
121
|
+
};
|
|
122
|
+
return await loadPage({
|
|
123
|
+
pageSizeVar: "last",
|
|
124
|
+
functionName: "loadPreviousPage",
|
|
125
|
+
input,
|
|
126
|
+
fetch,
|
|
127
|
+
metadata,
|
|
128
|
+
where: "start"
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
async fetch(args) {
|
|
132
|
+
const { variables } = args ?? {};
|
|
133
|
+
if (variables && !(0, import_deepEquals.deepEquals)(getVariables(), variables)) {
|
|
134
|
+
return await parentFetch(args);
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
var currentPageInfo = (0, import_pageInfo.extractPageInfo)(getState(), artifact.refetch.path);
|
|
138
|
+
} catch {
|
|
139
|
+
return await parentFetch(args);
|
|
140
|
+
}
|
|
141
|
+
const queryVariables = {};
|
|
142
|
+
const count = (0, import_pageInfo.countPage)(artifact.refetch.path.concat("edges"), getState()) || artifact.refetch.pageSize;
|
|
143
|
+
if (count && count > artifact.refetch.pageSize) {
|
|
144
|
+
if (currentPageInfo.hasPreviousPage && currentPageInfo.hasNextPage && !(variables?.["first"] && variables?.["after"] || variables?.["last"] && variables?.["before"])) {
|
|
145
|
+
console.warn(`\u26A0\uFE0F Encountered a fetch() in the middle of the connection.
|
|
146
|
+
Make sure to pass a cursor value by hand that includes the current set (ie the entry before startCursor)
|
|
147
|
+
`);
|
|
148
|
+
}
|
|
149
|
+
if (!currentPageInfo.hasPreviousPage) {
|
|
150
|
+
queryVariables["first"] = count;
|
|
151
|
+
queryVariables["after"] = null;
|
|
152
|
+
queryVariables["last"] = null;
|
|
153
|
+
queryVariables["before"] = null;
|
|
154
|
+
} else if (!currentPageInfo.hasNextPage) {
|
|
155
|
+
queryVariables["last"] = count;
|
|
156
|
+
queryVariables["first"] = null;
|
|
157
|
+
queryVariables["after"] = null;
|
|
158
|
+
queryVariables["before"] = null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
Object.assign(queryVariables, variables ?? {});
|
|
162
|
+
const result = await parentFetch({
|
|
163
|
+
...args,
|
|
164
|
+
variables: queryVariables
|
|
165
|
+
});
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function offsetHandlers({
|
|
171
|
+
artifact,
|
|
172
|
+
storeName,
|
|
173
|
+
getState,
|
|
174
|
+
getVariables,
|
|
175
|
+
fetch: parentFetch,
|
|
176
|
+
fetchUpdate: parentFetchUpdate,
|
|
177
|
+
getSession
|
|
178
|
+
}) {
|
|
179
|
+
let getOffset = () => artifact.refetch?.start || (0, import_pageInfo.countPage)(artifact.refetch.path, getState()) || artifact.refetch.pageSize;
|
|
180
|
+
let currentOffset = getOffset() ?? 0;
|
|
181
|
+
return {
|
|
182
|
+
loadNextPage: async ({
|
|
183
|
+
limit,
|
|
184
|
+
offset,
|
|
185
|
+
fetch,
|
|
186
|
+
metadata
|
|
187
|
+
} = {}) => {
|
|
188
|
+
const queryVariables = {
|
|
189
|
+
...getVariables(),
|
|
190
|
+
offset: offset ?? getOffset()
|
|
191
|
+
};
|
|
192
|
+
if (limit || limit === 0) {
|
|
193
|
+
queryVariables.limit = limit;
|
|
194
|
+
}
|
|
195
|
+
if (!queryVariables.limit && !artifact.refetch.pageSize) {
|
|
196
|
+
throw (0, import_pageInfo.missingPageSizeError)("loadNextPage");
|
|
197
|
+
}
|
|
198
|
+
let isSinglePage = artifact.refetch?.mode === "SinglePage";
|
|
199
|
+
const targetFetch = isSinglePage ? parentFetch : parentFetchUpdate;
|
|
200
|
+
await targetFetch({
|
|
201
|
+
variables: queryVariables,
|
|
202
|
+
fetch,
|
|
203
|
+
metadata,
|
|
204
|
+
policy: isSinglePage ? artifact.policy : import_types.CachePolicy.NetworkOnly,
|
|
205
|
+
session: await getSession()
|
|
206
|
+
});
|
|
207
|
+
const pageSize = queryVariables.limit || artifact.refetch.pageSize;
|
|
208
|
+
currentOffset = offset + pageSize;
|
|
209
|
+
},
|
|
210
|
+
async fetch(params = {}) {
|
|
211
|
+
const { variables } = params;
|
|
212
|
+
if (variables && !(0, import_deepEquals.deepEquals)(getVariables(), variables)) {
|
|
213
|
+
return parentFetch.call(this, params);
|
|
214
|
+
}
|
|
215
|
+
const count = currentOffset || getOffset();
|
|
216
|
+
const queryVariables = {};
|
|
217
|
+
if (!artifact.refetch.pageSize || count > artifact.refetch.pageSize) {
|
|
218
|
+
queryVariables.limit = count;
|
|
219
|
+
}
|
|
220
|
+
return await parentFetch.call(this, {
|
|
221
|
+
...params,
|
|
222
|
+
variables: queryVariables
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
228
|
+
0 && (module.exports = {
|
|
229
|
+
cursorHandlers,
|
|
230
|
+
offsetHandlers
|
|
231
|
+
});
|
|
@@ -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;
|
|
@@ -5,6 +5,9 @@ import { Writable } from '../lib/store';
|
|
|
5
5
|
import type { DocumentArtifact, QueryResult, GraphQLObject, SubscriptionSpec, CachePolicies } from '../lib/types';
|
|
6
6
|
export declare class DocumentStore<_Data extends GraphQLObject, _Input extends Record<string, any>> extends Writable<QueryResult<_Data, _Input>> {
|
|
7
7
|
#private;
|
|
8
|
+
pendingPromise: {
|
|
9
|
+
then: (val: any) => void;
|
|
10
|
+
} | null;
|
|
8
11
|
constructor({ artifact, plugins, pipeline, client, cache, initialValue, fetching, }: {
|
|
9
12
|
artifact: DocumentArtifact;
|
|
10
13
|
plugins?: ClientHooks[];
|
|
@@ -15,6 +15,7 @@ class DocumentStore extends Writable {
|
|
|
15
15
|
#plugins;
|
|
16
16
|
#lastVariables;
|
|
17
17
|
#lastContext = null;
|
|
18
|
+
pendingPromise = null;
|
|
18
19
|
constructor({
|
|
19
20
|
artifact,
|
|
20
21
|
plugins,
|
|
@@ -87,7 +88,7 @@ class DocumentStore extends Writable {
|
|
|
87
88
|
const draft = context.draft();
|
|
88
89
|
draft.variables = variables ?? null;
|
|
89
90
|
context = context.apply(draft, false);
|
|
90
|
-
|
|
91
|
+
const promise = new Promise((resolve, reject) => {
|
|
91
92
|
const state = {
|
|
92
93
|
setup,
|
|
93
94
|
currentStep: 0,
|
|
@@ -96,12 +97,17 @@ class DocumentStore extends Writable {
|
|
|
96
97
|
promise: {
|
|
97
98
|
resolved: false,
|
|
98
99
|
resolve,
|
|
99
|
-
reject
|
|
100
|
+
reject,
|
|
101
|
+
then: (...args) => promise.then(...args)
|
|
100
102
|
},
|
|
101
103
|
context
|
|
102
104
|
};
|
|
105
|
+
if (this.pendingPromise === null) {
|
|
106
|
+
this.pendingPromise = state.promise;
|
|
107
|
+
}
|
|
103
108
|
this.#step("forward", state);
|
|
104
109
|
});
|
|
110
|
+
return await promise;
|
|
105
111
|
}
|
|
106
112
|
async cleanup() {
|
|
107
113
|
for (const plugin of this.#plugins) {
|
|
@@ -220,16 +226,15 @@ class DocumentStore extends Writable {
|
|
|
220
226
|
value
|
|
221
227
|
);
|
|
222
228
|
}
|
|
229
|
+
if (!ctx.silenceEcho || value.data !== this.state.data) {
|
|
230
|
+
this.set(value);
|
|
231
|
+
}
|
|
223
232
|
if (!ctx.promise.resolved) {
|
|
224
233
|
ctx.promise.resolve(value);
|
|
225
234
|
ctx.promise.resolved = true;
|
|
226
235
|
}
|
|
227
236
|
this.#lastContext = ctx.context.draft();
|
|
228
237
|
this.#lastVariables = this.#lastContext.stuff.inputs.marshaled;
|
|
229
|
-
if (ctx.silenceEcho && value.data === this.state.data) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
this.set(value);
|
|
233
238
|
}
|
|
234
239
|
}
|
|
235
240
|
class ClientPluginContextWrapper {
|
|
@@ -3,7 +3,7 @@ import type { DocumentArtifact, GraphQLObject, NestedList } from '../lib/types';
|
|
|
3
3
|
import type { ClientPlugin, ClientHooks } from './documentStore';
|
|
4
4
|
import { DocumentStore } from './documentStore';
|
|
5
5
|
import { type FetchParamFn, type ThrowOnErrorParams } from './plugins';
|
|
6
|
-
export { DocumentStore, type ClientPlugin } from './documentStore';
|
|
6
|
+
export { DocumentStore, type ClientPlugin, type SendParams } from './documentStore';
|
|
7
7
|
export { fetch, mutation, query, subscription } from './plugins';
|
|
8
8
|
type ConstructorArgs = {
|
|
9
9
|
url: string;
|
|
@@ -12,11 +12,12 @@ const cachePolicy = ({
|
|
|
12
12
|
network(ctx, { initialValue, next, resolve, marshalVariables }) {
|
|
13
13
|
const { policy, artifact } = ctx;
|
|
14
14
|
let useCache = false;
|
|
15
|
-
if (enabled && artifact.kind === ArtifactKind.Query && !ctx.cacheParams?.disableRead) {
|
|
15
|
+
if (enabled && (artifact.kind === ArtifactKind.Query || artifact.kind === ArtifactKind.Fragment) && !ctx.cacheParams?.disableRead) {
|
|
16
16
|
if (policy !== CachePolicy.NetworkOnly) {
|
|
17
17
|
const value = localCache.read({
|
|
18
18
|
selection: artifact.selection,
|
|
19
|
-
variables: marshalVariables(ctx)
|
|
19
|
+
variables: marshalVariables(ctx),
|
|
20
|
+
parent: ctx.stuff?.parentID
|
|
20
21
|
});
|
|
21
22
|
const allowed = !value.partial || artifact.kind === ArtifactKind.Query && artifact.partial;
|
|
22
23
|
if (policy === CachePolicy.CacheOnly) {
|
|
@@ -52,7 +53,9 @@ const cachePolicy = ({
|
|
|
52
53
|
localCache._internal_unstable.collectGarbage();
|
|
53
54
|
}, 0);
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
+
if (!ctx.stuff?.silenceLoading) {
|
|
57
|
+
setFetching(!useCache);
|
|
58
|
+
}
|
|
56
59
|
return next(ctx);
|
|
57
60
|
},
|
|
58
61
|
afterNetwork(ctx, { resolve, value, marshalVariables }) {
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import cache from "../../cache";
|
|
2
|
+
import { deepEquals } from "../../lib/deepEquals";
|
|
2
3
|
import { ArtifactKind, DataSource } from "../../lib/types";
|
|
3
4
|
import { documentPlugin } from "../utils";
|
|
4
5
|
const fragment = documentPlugin(ArtifactKind.Fragment, function() {
|
|
5
6
|
let subscriptionSpec = null;
|
|
7
|
+
let lastReference = null;
|
|
6
8
|
return {
|
|
7
9
|
start(ctx, { next, resolve, variablesChanged, marshalVariables }) {
|
|
8
10
|
if (!ctx.stuff.parentID) {
|
|
9
11
|
return next(ctx);
|
|
10
12
|
}
|
|
11
|
-
|
|
13
|
+
const currentReference = {
|
|
14
|
+
parent: ctx.stuff.parentID,
|
|
15
|
+
variables: marshalVariables(ctx)
|
|
16
|
+
};
|
|
17
|
+
if (!ctx.cacheParams?.disableSubscriptions && (!deepEquals(lastReference, currentReference) || variablesChanged(ctx))) {
|
|
12
18
|
if (subscriptionSpec) {
|
|
13
19
|
cache.unsubscribe(subscriptionSpec, subscriptionSpec.variables?.() || {});
|
|
14
20
|
}
|
|
@@ -31,6 +37,7 @@ const fragment = documentPlugin(ArtifactKind.Fragment, function() {
|
|
|
31
37
|
}
|
|
32
38
|
};
|
|
33
39
|
cache.subscribe(subscriptionSpec, variables);
|
|
40
|
+
lastReference = currentReference;
|
|
34
41
|
}
|
|
35
42
|
next(ctx);
|
|
36
43
|
},
|
|
@@ -18,10 +18,11 @@ const query = documentPlugin(ArtifactKind.Query, function() {
|
|
|
18
18
|
cache.unsubscribe(subscriptionSpec, subscriptionSpec.variables?.() || {});
|
|
19
19
|
}
|
|
20
20
|
lastVariables = { ...marshalVariables(ctx) };
|
|
21
|
+
const variables = lastVariables;
|
|
21
22
|
subscriptionSpec = {
|
|
22
23
|
rootType: ctx.artifact.rootType,
|
|
23
24
|
selection: ctx.artifact.selection,
|
|
24
|
-
variables: () =>
|
|
25
|
+
variables: () => variables,
|
|
25
26
|
set: (newValue) => {
|
|
26
27
|
resolve(ctx, {
|
|
27
28
|
data: newValue,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { GraphQLObject, PageInfo } from './types';
|
|
2
|
+
export declare function nullPageInfo(): PageInfo;
|
|
3
|
+
export declare function missingPageSizeError(fnName: string): {
|
|
4
|
+
message: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function extractPageInfo(data: any, path: string[]): PageInfo;
|
|
7
|
+
export declare function countPage<_Data extends GraphQLObject>(source: string[], value: _Data | null): number;
|