@envelop/response-cache 5.3.2 → 5.4.0-alpha-20231002122542-47bd2dfa
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/cjs/plugin.js +77 -55
- package/esm/plugin.js +77 -55
- package/package.json +1 -1
package/cjs/plugin.js
CHANGED
|
@@ -41,38 +41,8 @@ function defaultGetDocumentString(executionArgs) {
|
|
|
41
41
|
}
|
|
42
42
|
exports.defaultGetDocumentString = defaultGetDocumentString;
|
|
43
43
|
const originalDocumentMap = new WeakMap();
|
|
44
|
-
const addTypeNameToDocument = (0, utils_1.memoize2)(function addTypeNameToDocument(document,
|
|
45
|
-
const newDocument = (0, graphql_1.visit)(document,
|
|
46
|
-
OperationDefinition: {
|
|
47
|
-
enter(node) {
|
|
48
|
-
if (!addTypeNameToDocumentOpts.invalidateViaMutation && node.operation === 'mutation') {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
if (node.operation === 'subscription') {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
SelectionSet(node, _key, parent) {
|
|
57
|
-
return {
|
|
58
|
-
...node,
|
|
59
|
-
selections: [
|
|
60
|
-
{
|
|
61
|
-
kind: graphql_1.Kind.FIELD,
|
|
62
|
-
name: {
|
|
63
|
-
kind: graphql_1.Kind.NAME,
|
|
64
|
-
value: '__typename',
|
|
65
|
-
},
|
|
66
|
-
alias: {
|
|
67
|
-
kind: graphql_1.Kind.NAME,
|
|
68
|
-
value: '__responseCacheTypeName',
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
...node.selections,
|
|
72
|
-
],
|
|
73
|
-
};
|
|
74
|
-
},
|
|
75
|
-
});
|
|
44
|
+
const addTypeNameToDocument = (0, utils_1.memoize2)(function addTypeNameToDocument(document, visitor) {
|
|
45
|
+
const newDocument = (0, graphql_1.visit)(document, visitor);
|
|
76
46
|
originalDocumentMap.set(newDocument, document);
|
|
77
47
|
return newDocument;
|
|
78
48
|
});
|
|
@@ -81,28 +51,31 @@ function useResponseCache({ cache = (0, in_memory_cache_js_1.createInMemoryCache
|
|
|
81
51
|
process.env['NODE_ENV'] === 'development' || !!process.env['DEBUG']
|
|
82
52
|
: false, }) {
|
|
83
53
|
const ignoredTypesMap = new Set(ignoredTypes);
|
|
84
|
-
const processedSchemas = new
|
|
54
|
+
const processedSchemas = new WeakMap();
|
|
85
55
|
// never cache Introspections
|
|
86
56
|
ttlPerSchemaCoordinate = { 'Query.__schema': 0, ...ttlPerSchemaCoordinate };
|
|
87
57
|
const addTypeNameToDocumentOpts = { invalidateViaMutation };
|
|
58
|
+
const idFieldByTypeName = new Map();
|
|
59
|
+
let visitor;
|
|
88
60
|
return {
|
|
89
61
|
onParse() {
|
|
90
62
|
return ({ result, replaceParseResult }) => {
|
|
91
63
|
if (!originalDocumentMap.has(result) && result.kind === graphql_1.Kind.DOCUMENT) {
|
|
92
|
-
const newDocument = addTypeNameToDocument(result,
|
|
64
|
+
const newDocument = addTypeNameToDocument(result, visitor);
|
|
93
65
|
replaceParseResult(newDocument);
|
|
94
66
|
}
|
|
95
67
|
};
|
|
96
68
|
},
|
|
97
69
|
onSchemaChange({ schema }) {
|
|
98
70
|
if (processedSchemas.has(schema)) {
|
|
71
|
+
visitor = processedSchemas.get(schema);
|
|
99
72
|
return;
|
|
100
73
|
}
|
|
101
74
|
// Check if the schema has @cacheControl directive
|
|
102
75
|
const cacheControlDirective = schema.getDirective('cacheControl');
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
76
|
+
(0, utils_1.mapSchema)(schema, {
|
|
77
|
+
[utils_1.MapperKind.COMPOSITE_TYPE]: type => {
|
|
78
|
+
if (cacheControlDirective) {
|
|
106
79
|
const cacheControlAnnotations = (0, utils_1.getDirective)(schema, type, 'cacheControl');
|
|
107
80
|
cacheControlAnnotations?.forEach(cacheControl => {
|
|
108
81
|
const ttl = cacheControl.maxAge * 1000;
|
|
@@ -113,24 +86,73 @@ function useResponseCache({ cache = (0, in_memory_cache_js_1.createInMemoryCache
|
|
|
113
86
|
scopePerSchemaCoordinate[`${type.name}`] = cacheControl.scope;
|
|
114
87
|
}
|
|
115
88
|
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
89
|
+
}
|
|
90
|
+
return type;
|
|
91
|
+
},
|
|
92
|
+
[utils_1.MapperKind.FIELD]: (fieldConfig, fieldName, typeName) => {
|
|
93
|
+
if (idFields.includes(fieldName) && !idFieldByTypeName.has(typeName)) {
|
|
94
|
+
idFieldByTypeName.set(typeName, fieldName);
|
|
95
|
+
}
|
|
96
|
+
if (cacheControlDirective) {
|
|
97
|
+
const schemaCoordinate = `${typeName}.${fieldName}`;
|
|
119
98
|
const cacheControlAnnotations = (0, utils_1.getDirective)(schema, fieldConfig, 'cacheControl');
|
|
120
99
|
cacheControlAnnotations?.forEach(cacheControl => {
|
|
121
100
|
const ttl = cacheControl.maxAge * 1000;
|
|
122
101
|
if (ttl != null) {
|
|
123
|
-
ttlPerSchemaCoordinate[
|
|
102
|
+
ttlPerSchemaCoordinate[schemaCoordinate] = ttl;
|
|
124
103
|
}
|
|
125
104
|
if (cacheControl.scope) {
|
|
126
|
-
scopePerSchemaCoordinate[
|
|
105
|
+
scopePerSchemaCoordinate[schemaCoordinate] = cacheControl.scope;
|
|
127
106
|
}
|
|
128
107
|
});
|
|
129
|
-
|
|
108
|
+
}
|
|
109
|
+
return fieldConfig;
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
const typeInfo = new graphql_1.TypeInfo(schema);
|
|
113
|
+
visitor = (0, graphql_1.visitWithTypeInfo)(typeInfo, {
|
|
114
|
+
OperationDefinition: {
|
|
115
|
+
enter(node) {
|
|
116
|
+
if (!addTypeNameToDocumentOpts.invalidateViaMutation && node.operation === 'mutation') {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
if (node.operation === 'subscription') {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
130
122
|
},
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
123
|
+
},
|
|
124
|
+
SelectionSet(node, _key, parent) {
|
|
125
|
+
const parentType = typeInfo.getParentType();
|
|
126
|
+
const idField = parentType && idFieldByTypeName.get(parentType.name);
|
|
127
|
+
return {
|
|
128
|
+
...node,
|
|
129
|
+
selections: [
|
|
130
|
+
{
|
|
131
|
+
kind: graphql_1.Kind.FIELD,
|
|
132
|
+
name: {
|
|
133
|
+
kind: graphql_1.Kind.NAME,
|
|
134
|
+
value: '__typename',
|
|
135
|
+
},
|
|
136
|
+
alias: {
|
|
137
|
+
kind: graphql_1.Kind.NAME,
|
|
138
|
+
value: '__responseCacheTypeName',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
...(idField
|
|
142
|
+
? [
|
|
143
|
+
{
|
|
144
|
+
kind: graphql_1.Kind.FIELD,
|
|
145
|
+
name: { kind: graphql_1.Kind.NAME, value: idField },
|
|
146
|
+
alias: { kind: graphql_1.Kind.NAME, value: '__responseCacheId' },
|
|
147
|
+
},
|
|
148
|
+
]
|
|
149
|
+
: []),
|
|
150
|
+
...node.selections,
|
|
151
|
+
],
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
processedSchemas.set(schema, visitor);
|
|
134
156
|
},
|
|
135
157
|
async onExecute(onExecuteParams) {
|
|
136
158
|
const identifier = new Map();
|
|
@@ -150,6 +172,8 @@ function useResponseCache({ cache = (0, in_memory_cache_js_1.createInMemoryCache
|
|
|
150
172
|
}
|
|
151
173
|
const typename = data.__responseCacheTypeName;
|
|
152
174
|
delete data.__responseCacheTypeName;
|
|
175
|
+
const entityId = data.__responseCacheId;
|
|
176
|
+
delete data.__responseCacheId;
|
|
153
177
|
if (!skip) {
|
|
154
178
|
if (ignoredTypesMap.has(typename) ||
|
|
155
179
|
(scopePerSchemaCoordinate[typename] === 'PRIVATE' && !sessionId)) {
|
|
@@ -160,16 +184,14 @@ function useResponseCache({ cache = (0, in_memory_cache_js_1.createInMemoryCache
|
|
|
160
184
|
if (typename in ttlPerType) {
|
|
161
185
|
currentTtl = calculateTtl(ttlPerType[typename], currentTtl);
|
|
162
186
|
}
|
|
187
|
+
if (entityId != null) {
|
|
188
|
+
identifier.set(`${typename}:${entityId}`, { typename, id: entityId });
|
|
189
|
+
}
|
|
163
190
|
for (const fieldName in data) {
|
|
164
|
-
if (!skip
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
else if (idFields.includes(fieldName)) {
|
|
170
|
-
const id = data[fieldName];
|
|
171
|
-
identifier.set(`${typename}:${id}`, { typename, id });
|
|
172
|
-
}
|
|
191
|
+
if (!skip &&
|
|
192
|
+
scopePerSchemaCoordinate[`${typename}.${fieldName}`] === 'PRIVATE' &&
|
|
193
|
+
!sessionId) {
|
|
194
|
+
skip = true;
|
|
173
195
|
}
|
|
174
196
|
processResult(data[fieldName]);
|
|
175
197
|
}
|
package/esm/plugin.js
CHANGED
|
@@ -34,38 +34,8 @@ export function defaultGetDocumentString(executionArgs) {
|
|
|
34
34
|
return getDocumentString(executionArgs.document, print);
|
|
35
35
|
}
|
|
36
36
|
const originalDocumentMap = new WeakMap();
|
|
37
|
-
const addTypeNameToDocument = memoize2(function addTypeNameToDocument(document,
|
|
38
|
-
const newDocument = visit(document,
|
|
39
|
-
OperationDefinition: {
|
|
40
|
-
enter(node) {
|
|
41
|
-
if (!addTypeNameToDocumentOpts.invalidateViaMutation && node.operation === 'mutation') {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
if (node.operation === 'subscription') {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
SelectionSet(node, _key, parent) {
|
|
50
|
-
return {
|
|
51
|
-
...node,
|
|
52
|
-
selections: [
|
|
53
|
-
{
|
|
54
|
-
kind: Kind.FIELD,
|
|
55
|
-
name: {
|
|
56
|
-
kind: Kind.NAME,
|
|
57
|
-
value: '__typename',
|
|
58
|
-
},
|
|
59
|
-
alias: {
|
|
60
|
-
kind: Kind.NAME,
|
|
61
|
-
value: '__responseCacheTypeName',
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
...node.selections,
|
|
65
|
-
],
|
|
66
|
-
};
|
|
67
|
-
},
|
|
68
|
-
});
|
|
37
|
+
const addTypeNameToDocument = memoize2(function addTypeNameToDocument(document, visitor) {
|
|
38
|
+
const newDocument = visit(document, visitor);
|
|
69
39
|
originalDocumentMap.set(newDocument, document);
|
|
70
40
|
return newDocument;
|
|
71
41
|
});
|
|
@@ -74,28 +44,31 @@ export function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl
|
|
|
74
44
|
process.env['NODE_ENV'] === 'development' || !!process.env['DEBUG']
|
|
75
45
|
: false, }) {
|
|
76
46
|
const ignoredTypesMap = new Set(ignoredTypes);
|
|
77
|
-
const processedSchemas = new
|
|
47
|
+
const processedSchemas = new WeakMap();
|
|
78
48
|
// never cache Introspections
|
|
79
49
|
ttlPerSchemaCoordinate = { 'Query.__schema': 0, ...ttlPerSchemaCoordinate };
|
|
80
50
|
const addTypeNameToDocumentOpts = { invalidateViaMutation };
|
|
51
|
+
const idFieldByTypeName = new Map();
|
|
52
|
+
let visitor;
|
|
81
53
|
return {
|
|
82
54
|
onParse() {
|
|
83
55
|
return ({ result, replaceParseResult }) => {
|
|
84
56
|
if (!originalDocumentMap.has(result) && result.kind === Kind.DOCUMENT) {
|
|
85
|
-
const newDocument = addTypeNameToDocument(result,
|
|
57
|
+
const newDocument = addTypeNameToDocument(result, visitor);
|
|
86
58
|
replaceParseResult(newDocument);
|
|
87
59
|
}
|
|
88
60
|
};
|
|
89
61
|
},
|
|
90
62
|
onSchemaChange({ schema }) {
|
|
91
63
|
if (processedSchemas.has(schema)) {
|
|
64
|
+
visitor = processedSchemas.get(schema);
|
|
92
65
|
return;
|
|
93
66
|
}
|
|
94
67
|
// Check if the schema has @cacheControl directive
|
|
95
68
|
const cacheControlDirective = schema.getDirective('cacheControl');
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
69
|
+
mapSchema(schema, {
|
|
70
|
+
[MapperKind.COMPOSITE_TYPE]: type => {
|
|
71
|
+
if (cacheControlDirective) {
|
|
99
72
|
const cacheControlAnnotations = getDirective(schema, type, 'cacheControl');
|
|
100
73
|
cacheControlAnnotations?.forEach(cacheControl => {
|
|
101
74
|
const ttl = cacheControl.maxAge * 1000;
|
|
@@ -106,24 +79,73 @@ export function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl
|
|
|
106
79
|
scopePerSchemaCoordinate[`${type.name}`] = cacheControl.scope;
|
|
107
80
|
}
|
|
108
81
|
});
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
82
|
+
}
|
|
83
|
+
return type;
|
|
84
|
+
},
|
|
85
|
+
[MapperKind.FIELD]: (fieldConfig, fieldName, typeName) => {
|
|
86
|
+
if (idFields.includes(fieldName) && !idFieldByTypeName.has(typeName)) {
|
|
87
|
+
idFieldByTypeName.set(typeName, fieldName);
|
|
88
|
+
}
|
|
89
|
+
if (cacheControlDirective) {
|
|
90
|
+
const schemaCoordinate = `${typeName}.${fieldName}`;
|
|
112
91
|
const cacheControlAnnotations = getDirective(schema, fieldConfig, 'cacheControl');
|
|
113
92
|
cacheControlAnnotations?.forEach(cacheControl => {
|
|
114
93
|
const ttl = cacheControl.maxAge * 1000;
|
|
115
94
|
if (ttl != null) {
|
|
116
|
-
ttlPerSchemaCoordinate[
|
|
95
|
+
ttlPerSchemaCoordinate[schemaCoordinate] = ttl;
|
|
117
96
|
}
|
|
118
97
|
if (cacheControl.scope) {
|
|
119
|
-
scopePerSchemaCoordinate[
|
|
98
|
+
scopePerSchemaCoordinate[schemaCoordinate] = cacheControl.scope;
|
|
120
99
|
}
|
|
121
100
|
});
|
|
122
|
-
|
|
101
|
+
}
|
|
102
|
+
return fieldConfig;
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
const typeInfo = new TypeInfo(schema);
|
|
106
|
+
visitor = visitWithTypeInfo(typeInfo, {
|
|
107
|
+
OperationDefinition: {
|
|
108
|
+
enter(node) {
|
|
109
|
+
if (!addTypeNameToDocumentOpts.invalidateViaMutation && node.operation === 'mutation') {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
if (node.operation === 'subscription') {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
123
115
|
},
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
116
|
+
},
|
|
117
|
+
SelectionSet(node, _key, parent) {
|
|
118
|
+
const parentType = typeInfo.getParentType();
|
|
119
|
+
const idField = parentType && idFieldByTypeName.get(parentType.name);
|
|
120
|
+
return {
|
|
121
|
+
...node,
|
|
122
|
+
selections: [
|
|
123
|
+
{
|
|
124
|
+
kind: Kind.FIELD,
|
|
125
|
+
name: {
|
|
126
|
+
kind: Kind.NAME,
|
|
127
|
+
value: '__typename',
|
|
128
|
+
},
|
|
129
|
+
alias: {
|
|
130
|
+
kind: Kind.NAME,
|
|
131
|
+
value: '__responseCacheTypeName',
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
...(idField
|
|
135
|
+
? [
|
|
136
|
+
{
|
|
137
|
+
kind: Kind.FIELD,
|
|
138
|
+
name: { kind: Kind.NAME, value: idField },
|
|
139
|
+
alias: { kind: Kind.NAME, value: '__responseCacheId' },
|
|
140
|
+
},
|
|
141
|
+
]
|
|
142
|
+
: []),
|
|
143
|
+
...node.selections,
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
processedSchemas.set(schema, visitor);
|
|
127
149
|
},
|
|
128
150
|
async onExecute(onExecuteParams) {
|
|
129
151
|
const identifier = new Map();
|
|
@@ -143,6 +165,8 @@ export function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl
|
|
|
143
165
|
}
|
|
144
166
|
const typename = data.__responseCacheTypeName;
|
|
145
167
|
delete data.__responseCacheTypeName;
|
|
168
|
+
const entityId = data.__responseCacheId;
|
|
169
|
+
delete data.__responseCacheId;
|
|
146
170
|
if (!skip) {
|
|
147
171
|
if (ignoredTypesMap.has(typename) ||
|
|
148
172
|
(scopePerSchemaCoordinate[typename] === 'PRIVATE' && !sessionId)) {
|
|
@@ -153,16 +177,14 @@ export function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl
|
|
|
153
177
|
if (typename in ttlPerType) {
|
|
154
178
|
currentTtl = calculateTtl(ttlPerType[typename], currentTtl);
|
|
155
179
|
}
|
|
180
|
+
if (entityId != null) {
|
|
181
|
+
identifier.set(`${typename}:${entityId}`, { typename, id: entityId });
|
|
182
|
+
}
|
|
156
183
|
for (const fieldName in data) {
|
|
157
|
-
if (!skip
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
else if (idFields.includes(fieldName)) {
|
|
163
|
-
const id = data[fieldName];
|
|
164
|
-
identifier.set(`${typename}:${id}`, { typename, id });
|
|
165
|
-
}
|
|
184
|
+
if (!skip &&
|
|
185
|
+
scopePerSchemaCoordinate[`${typename}.${fieldName}`] === 'PRIVATE' &&
|
|
186
|
+
!sessionId) {
|
|
187
|
+
skip = true;
|
|
166
188
|
}
|
|
167
189
|
processResult(data[fieldName]);
|
|
168
190
|
}
|