@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 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, addTypeNameToDocumentOpts) {
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 WeakSet();
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, addTypeNameToDocumentOpts);
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
- if (cacheControlDirective) {
104
- (0, utils_1.mapSchema)(schema, {
105
- [utils_1.MapperKind.COMPOSITE_TYPE]: type => {
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
- return type;
117
- },
118
- [utils_1.MapperKind.FIELD]: (fieldConfig, fieldName, typeName) => {
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[`${typeName}.${fieldName}`] = ttl;
102
+ ttlPerSchemaCoordinate[schemaCoordinate] = ttl;
124
103
  }
125
104
  if (cacheControl.scope) {
126
- scopePerSchemaCoordinate[`${typeName}.${fieldName}`] = cacheControl.scope;
105
+ scopePerSchemaCoordinate[schemaCoordinate] = cacheControl.scope;
127
106
  }
128
107
  });
129
- return fieldConfig;
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
- processedSchemas.add(schema);
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
- if (scopePerSchemaCoordinate[`${typename}.${fieldName}`] === 'PRIVATE' &&
166
- !sessionId) {
167
- skip = true;
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, addTypeNameToDocumentOpts) {
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 WeakSet();
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, addTypeNameToDocumentOpts);
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
- if (cacheControlDirective) {
97
- mapSchema(schema, {
98
- [MapperKind.COMPOSITE_TYPE]: type => {
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
- return type;
110
- },
111
- [MapperKind.FIELD]: (fieldConfig, fieldName, typeName) => {
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[`${typeName}.${fieldName}`] = ttl;
95
+ ttlPerSchemaCoordinate[schemaCoordinate] = ttl;
117
96
  }
118
97
  if (cacheControl.scope) {
119
- scopePerSchemaCoordinate[`${typeName}.${fieldName}`] = cacheControl.scope;
98
+ scopePerSchemaCoordinate[schemaCoordinate] = cacheControl.scope;
120
99
  }
121
100
  });
122
- return fieldConfig;
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
- processedSchemas.add(schema);
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
- if (scopePerSchemaCoordinate[`${typename}.${fieldName}`] === 'PRIVATE' &&
159
- !sessionId) {
160
- skip = true;
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@envelop/response-cache",
3
- "version": "5.3.2",
3
+ "version": "5.4.0-alpha-20231002122542-47bd2dfa",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
6
  "@envelop/core": "^4.0.3",