@graphql-box/connection-resolver 5.4.23-unstable-12345.2 → 5.4.23-unstable-12345.3
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/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/production.analysis.txt +66 -66
- package/dist/types/cjs/__testUtils__/generateCursorCache.d.cts.map +1 -1
- package/dist/types/cjs/helpers/cacheCursors.d.cts +2 -1
- package/dist/types/cjs/helpers/cacheCursors.d.cts.map +1 -1
- package/dist/types/cjs/helpers/requestAndCachePages.d.cts +2 -8
- package/dist/types/cjs/helpers/requestAndCachePages.d.cts.map +1 -1
- package/dist/types/cjs/types.d.cts +1 -0
- package/dist/types/cjs/types.d.cts.map +1 -1
- package/dist/types/esm/__testUtils__/generateCursorCache.d.ts.map +1 -1
- package/dist/types/esm/helpers/cacheCursors.d.ts +2 -1
- package/dist/types/esm/helpers/cacheCursors.d.ts.map +1 -1
- package/dist/types/esm/helpers/requestAndCachePages.d.ts +2 -8
- package/dist/types/esm/helpers/requestAndCachePages.d.ts.map +1 -1
- package/dist/types/esm/types.d.ts +1 -0
- package/dist/types/esm/types.d.ts.map +1 -1
- package/dist/types/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/src/__testUtils__/generateCursorCache.ts +6 -3
- package/src/helpers/cacheCursors.ts +4 -3
- package/src/helpers/getIndexesOnCurrentPage.test.ts +10 -2
- package/src/helpers/getPageNumbersToRequest.test.ts +2 -0
- package/src/helpers/getStartAndEndIndexes.test.ts +5 -0
- package/src/helpers/getStartAndEndPageNumbers.test.ts +5 -0
- package/src/helpers/requestAndCachePages.ts +47 -32
- package/src/helpers/validateCursor.test.ts +1 -1
- package/src/helpers/validateCursor.ts +1 -1
- package/src/types.ts +1 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-box/connection-resolver",
|
|
3
3
|
"description": "The GraphQL Box connection resolver module.",
|
|
4
|
-
"version": "5.4.23-unstable-12345.
|
|
4
|
+
"version": "5.4.23-unstable-12345.3",
|
|
5
5
|
"author": "miami-man",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/badbatch/graphql-box",
|
|
@@ -32,22 +32,22 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@cachemap/core": "^5.
|
|
35
|
+
"@cachemap/core": "^5.3.0",
|
|
36
36
|
"@types/lodash-es": "^4.17.12",
|
|
37
37
|
"core-js": "^3.43.0",
|
|
38
38
|
"js-base64": "^3.7.7",
|
|
39
|
-
"lodash-es": "^4.17.
|
|
39
|
+
"lodash-es": "^4.17.23",
|
|
40
40
|
"type-fest": "^4.41.0",
|
|
41
|
-
"@graphql-box/core": "5.4.14-unstable-12345.
|
|
41
|
+
"@graphql-box/core": "5.4.14-unstable-12345.3"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"graphql": "<17",
|
|
45
45
|
"winston": "<4"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@cachemap/map": "^5.0
|
|
48
|
+
"@cachemap/map": "^5.1.0",
|
|
49
49
|
"@jest/globals": "^29.3.1",
|
|
50
|
-
"cts-types": "^0.0.
|
|
50
|
+
"cts-types": "^0.0.11",
|
|
51
51
|
"del-cli": "^6.0.0",
|
|
52
52
|
"graphql": "^16.11.0",
|
|
53
53
|
"winston": "^3.17.0"
|
|
@@ -29,6 +29,7 @@ export const generateCursorCache = async ({
|
|
|
29
29
|
|
|
30
30
|
if (pageRanges.length > 0 && resultsPerPage) {
|
|
31
31
|
const pages = generatePages(pageRanges);
|
|
32
|
+
let cachedNodeIds: (string | number)[] = [];
|
|
32
33
|
|
|
33
34
|
await Promise.all(
|
|
34
35
|
pages.map(async page => {
|
|
@@ -47,14 +48,16 @@ export const generateCursorCache = async ({
|
|
|
47
48
|
return { cursor: `${id}::${group}`, node: { id } };
|
|
48
49
|
});
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
cachedNodeIds = [...cachedNodeIds, ...edges.map(edge => edge.node.id)];
|
|
52
|
+
|
|
53
|
+
await cacheCursors(cursorCache, { cachedNodeIds, edges, group, headers, page, totalPages, totalResults });
|
|
51
54
|
}),
|
|
52
55
|
);
|
|
53
56
|
} else {
|
|
54
57
|
await cursorCache.set(
|
|
55
58
|
`${group}-metadata`,
|
|
56
|
-
{ totalPages, totalResults },
|
|
57
|
-
{
|
|
59
|
+
{ cachedNodeIds: [], totalPages, totalResults },
|
|
60
|
+
{ cacheOptions: { cacheControl: headers.get('cache-control') ?? undefined } },
|
|
58
61
|
);
|
|
59
62
|
}
|
|
60
63
|
|
|
@@ -2,6 +2,7 @@ import { type Core } from '@cachemap/core';
|
|
|
2
2
|
import { type Edge } from '../types.ts';
|
|
3
3
|
|
|
4
4
|
export type Params = {
|
|
5
|
+
cachedNodeIds: (string | number)[];
|
|
5
6
|
edges: Edge[];
|
|
6
7
|
group: string;
|
|
7
8
|
headers: Headers;
|
|
@@ -12,14 +13,14 @@ export type Params = {
|
|
|
12
13
|
|
|
13
14
|
export const cacheCursors = async (
|
|
14
15
|
cursorCache: Core,
|
|
15
|
-
{ edges, group, headers, page, totalPages, totalResults }: Params,
|
|
16
|
+
{ cachedNodeIds, edges, group, headers, page, totalPages, totalResults }: Params,
|
|
16
17
|
) => {
|
|
17
18
|
const cacheControl = headers.get('cache-control');
|
|
18
|
-
const options = cacheControl ? {
|
|
19
|
+
const options = cacheControl ? { cacheOptions: { cacheControl } } : undefined;
|
|
19
20
|
|
|
20
21
|
await Promise.all(
|
|
21
22
|
edges.map(async ({ cursor, node }, index) => cursorCache.set(cursor, { group, index, node, page }, options)),
|
|
22
23
|
);
|
|
23
24
|
|
|
24
|
-
await cursorCache.set(`${group}-metadata`, { totalPages, totalResults }, options);
|
|
25
|
+
await cursorCache.set(`${group}-metadata`, { cachedNodeIds, totalPages, totalResults }, options);
|
|
25
26
|
};
|
|
@@ -4,7 +4,11 @@ describe('getIndexesOnCurrentPage', () => {
|
|
|
4
4
|
describe('when current page is last page', () => {
|
|
5
5
|
it('should return the correct value', () => {
|
|
6
6
|
expect(
|
|
7
|
-
getIndexesOnCurrentPage({
|
|
7
|
+
getIndexesOnCurrentPage({
|
|
8
|
+
metadata: { cachedNodeIds: [], totalPages: 6, totalResults: 53 },
|
|
9
|
+
page: 6,
|
|
10
|
+
resultsPerPage: 10,
|
|
11
|
+
}),
|
|
8
12
|
).toBe(2);
|
|
9
13
|
});
|
|
10
14
|
});
|
|
@@ -12,7 +16,11 @@ describe('getIndexesOnCurrentPage', () => {
|
|
|
12
16
|
describe('when current page is NOT last page', () => {
|
|
13
17
|
it('should return the correct value', () => {
|
|
14
18
|
expect(
|
|
15
|
-
getIndexesOnCurrentPage({
|
|
19
|
+
getIndexesOnCurrentPage({
|
|
20
|
+
metadata: { cachedNodeIds: [], totalPages: 6, totalResults: 53 },
|
|
21
|
+
page: 5,
|
|
22
|
+
resultsPerPage: 10,
|
|
23
|
+
}),
|
|
16
24
|
).toBe(9);
|
|
17
25
|
});
|
|
18
26
|
});
|
|
@@ -15,6 +15,7 @@ describe('getPageNumbersToRequest', () => {
|
|
|
15
15
|
page: 2,
|
|
16
16
|
},
|
|
17
17
|
metadata: {
|
|
18
|
+
cachedNodeIds: [],
|
|
18
19
|
totalPages: 5,
|
|
19
20
|
totalResults: 50,
|
|
20
21
|
},
|
|
@@ -41,6 +42,7 @@ describe('getPageNumbersToRequest', () => {
|
|
|
41
42
|
page: 4,
|
|
42
43
|
},
|
|
43
44
|
metadata: {
|
|
45
|
+
cachedNodeIds: [],
|
|
44
46
|
totalPages: 5,
|
|
45
47
|
totalResults: 50,
|
|
46
48
|
},
|
|
@@ -146,6 +146,7 @@ describe('getEndIndex', () => {
|
|
|
146
146
|
page: 3,
|
|
147
147
|
},
|
|
148
148
|
metadata: {
|
|
149
|
+
cachedNodeIds: [],
|
|
149
150
|
totalPages: 5,
|
|
150
151
|
totalResults: 50,
|
|
151
152
|
},
|
|
@@ -172,6 +173,7 @@ describe('getEndIndex', () => {
|
|
|
172
173
|
page: 6,
|
|
173
174
|
},
|
|
174
175
|
metadata: {
|
|
176
|
+
cachedNodeIds: [],
|
|
175
177
|
totalPages: 6,
|
|
176
178
|
totalResults: 57,
|
|
177
179
|
},
|
|
@@ -197,6 +199,7 @@ describe('getEndIndex', () => {
|
|
|
197
199
|
page: 6,
|
|
198
200
|
},
|
|
199
201
|
metadata: {
|
|
202
|
+
cachedNodeIds: [],
|
|
200
203
|
totalPages: 6,
|
|
201
204
|
totalResults: 57,
|
|
202
205
|
},
|
|
@@ -223,6 +226,7 @@ describe('getEndIndex', () => {
|
|
|
223
226
|
page: 4,
|
|
224
227
|
},
|
|
225
228
|
metadata: {
|
|
229
|
+
cachedNodeIds: [],
|
|
226
230
|
totalPages: 6,
|
|
227
231
|
totalResults: 57,
|
|
228
232
|
},
|
|
@@ -248,6 +252,7 @@ describe('getEndIndex', () => {
|
|
|
248
252
|
page: 4,
|
|
249
253
|
},
|
|
250
254
|
metadata: {
|
|
255
|
+
cachedNodeIds: [],
|
|
251
256
|
totalPages: 6,
|
|
252
257
|
totalResults: 57,
|
|
253
258
|
},
|
|
@@ -93,6 +93,7 @@ describe('getEndPageNumber', () => {
|
|
|
93
93
|
const ctx = {
|
|
94
94
|
endIndex: { absolute: 5, relative: 5 },
|
|
95
95
|
metadata: {
|
|
96
|
+
cachedNodeIds: [],
|
|
96
97
|
totalPages: 5,
|
|
97
98
|
totalResults: 50,
|
|
98
99
|
},
|
|
@@ -114,6 +115,7 @@ describe('getEndPageNumber', () => {
|
|
|
114
115
|
const ctx = {
|
|
115
116
|
endIndex: { absolute: 5, relative: 5 },
|
|
116
117
|
metadata: {
|
|
118
|
+
cachedNodeIds: [],
|
|
117
119
|
totalPages: 5,
|
|
118
120
|
totalResults: 50,
|
|
119
121
|
},
|
|
@@ -134,6 +136,7 @@ describe('getEndPageNumber', () => {
|
|
|
134
136
|
const ctx = {
|
|
135
137
|
endIndex: { absolute: 9, relative: 9 },
|
|
136
138
|
metadata: {
|
|
139
|
+
cachedNodeIds: [],
|
|
137
140
|
totalPages: 5,
|
|
138
141
|
totalResults: 50,
|
|
139
142
|
},
|
|
@@ -154,6 +157,7 @@ describe('getEndPageNumber', () => {
|
|
|
154
157
|
const ctx = {
|
|
155
158
|
endIndex: { absolute: 37, relative: 6 },
|
|
156
159
|
metadata: {
|
|
160
|
+
cachedNodeIds: [],
|
|
157
161
|
totalPages: 5,
|
|
158
162
|
totalResults: 50,
|
|
159
163
|
},
|
|
@@ -174,6 +178,7 @@ describe('getEndPageNumber', () => {
|
|
|
174
178
|
const ctx = {
|
|
175
179
|
endIndex: { absolute: 22, relative: 4 },
|
|
176
180
|
metadata: {
|
|
181
|
+
cachedNodeIds: [],
|
|
177
182
|
totalPages: 5,
|
|
178
183
|
totalResults: 50,
|
|
179
184
|
},
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { type Core } from '@cachemap/core';
|
|
2
2
|
import { type PlainObject } from '@graphql-box/core';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type CachedEdges,
|
|
5
|
+
type CursorGroupMetadata,
|
|
6
|
+
type Getters,
|
|
7
|
+
type Node,
|
|
8
|
+
type ResourceResolver,
|
|
9
|
+
type SetCacheMetadata,
|
|
10
|
+
} from '../types.ts';
|
|
4
11
|
import { cacheCursors } from './cacheCursors.ts';
|
|
5
12
|
import { makeEdges } from './makeEdges.ts';
|
|
6
13
|
|
|
@@ -14,6 +21,10 @@ export type Context<Resource extends PlainObject, ResourceNode extends Node> = {
|
|
|
14
21
|
setCacheMetadata: SetCacheMetadata | undefined;
|
|
15
22
|
};
|
|
16
23
|
|
|
24
|
+
const filterOutCachedNodes = (nodes: Node[], cachedNodeIds: (string | number)[]): Node[] => {
|
|
25
|
+
return nodes.filter(node => !cachedNodeIds.includes(node.id));
|
|
26
|
+
};
|
|
27
|
+
|
|
17
28
|
export const requestAndCachePages = async <Resource extends PlainObject, ResourceNode extends Node>(
|
|
18
29
|
pages: number[],
|
|
19
30
|
{
|
|
@@ -27,43 +38,47 @@ export const requestAndCachePages = async <Resource extends PlainObject, Resourc
|
|
|
27
38
|
}: Context<Resource, ResourceNode>,
|
|
28
39
|
) => {
|
|
29
40
|
const errors: Error[] = [];
|
|
41
|
+
const metadata = await cursorCache.get<CursorGroupMetadata>(`${groupCursor}-metadata`);
|
|
42
|
+
let cachedNodeIds = metadata?.cachedNodeIds ?? [];
|
|
43
|
+
const cachedEdges: CachedEdges[] = [];
|
|
30
44
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
});
|
|
45
|
+
for (const page of pages) {
|
|
46
|
+
const {
|
|
47
|
+
data: pageResultData,
|
|
48
|
+
errors: pageResultErrors,
|
|
49
|
+
headers: pageResultHeaders,
|
|
50
|
+
} = await resourceResolver({
|
|
51
|
+
page,
|
|
52
|
+
});
|
|
40
53
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
54
|
+
if (pageResultData) {
|
|
55
|
+
setCacheMetadata?.(fieldPath, pageResultHeaders);
|
|
56
|
+
}
|
|
44
57
|
|
|
45
|
-
|
|
46
|
-
|
|
58
|
+
if (pageResultData && !pageResultErrors?.length) {
|
|
59
|
+
const nodes = filterOutCachedNodes(getters.nodes(pageResultData), cachedNodeIds);
|
|
60
|
+
const edges = makeEdges(nodes, node => makeIDCursor(node.id));
|
|
61
|
+
cachedNodeIds = [...cachedNodeIds, ...edges.map(edge => edge.node.id)];
|
|
47
62
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return { edges, pageNumber: page };
|
|
58
|
-
}
|
|
63
|
+
await cacheCursors(cursorCache, {
|
|
64
|
+
cachedNodeIds,
|
|
65
|
+
edges,
|
|
66
|
+
group: groupCursor,
|
|
67
|
+
headers: pageResultHeaders,
|
|
68
|
+
page,
|
|
69
|
+
totalPages: getters.totalPages(pageResultData),
|
|
70
|
+
totalResults: getters.totalResults(pageResultData),
|
|
71
|
+
});
|
|
59
72
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
73
|
+
cachedEdges.push({ edges, pageNumber: page });
|
|
74
|
+
} else {
|
|
75
|
+
cachedEdges.push({ edges: [], pageNumber: page });
|
|
76
|
+
}
|
|
63
77
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
78
|
+
if (pageResultErrors?.length) {
|
|
79
|
+
errors.push(...pageResultErrors);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
67
82
|
|
|
68
83
|
return { cachedEdges, errors };
|
|
69
84
|
};
|
|
@@ -72,7 +72,7 @@ describe('validateCursor', () => {
|
|
|
72
72
|
|
|
73
73
|
it('should return the correct error', async () => {
|
|
74
74
|
const result = await validateCursor(args, info as GraphQLResolveInfo, ctx);
|
|
75
|
-
expect(result?.message).toBe('
|
|
75
|
+
expect(result?.message).toBe('Cursor cannot be supplied without previously being provided.');
|
|
76
76
|
});
|
|
77
77
|
});
|
|
78
78
|
|
|
@@ -48,7 +48,7 @@ export const validateCursor = async (
|
|
|
48
48
|
const metadata = await cursorCache.get<CursorGroupMetadata>(`${groupCursor}-metadata`);
|
|
49
49
|
|
|
50
50
|
if (!metadata) {
|
|
51
|
-
return new GraphQLError('
|
|
51
|
+
return new GraphQLError('Cursor cannot be supplied without previously being provided.', { nodes: fieldNodes });
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
const cursor = getCursor({ after, before });
|
package/src/types.ts
CHANGED