@common-stack/server-stack 7.0.4-alpha.16 → 7.0.4-alpha.18
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/lib/plugins/index.d.ts +1 -1
- package/lib/plugins/invalidateCachePlugin.cjs +19 -15
- package/lib/plugins/invalidateCachePlugin.cjs.map +1 -1
- package/lib/plugins/invalidateCachePlugin.mjs +19 -15
- package/lib/plugins/invalidateCachePlugin.mjs.map +1 -1
- package/lib/plugins/invalidateCachePlugin.test.d.ts +1 -0
- package/lib/plugins/response-cache-plugin.test.d.ts +1 -0
- package/lib/plugins/responseCachePlugin.cjs +42 -37
- package/lib/plugins/responseCachePlugin.cjs.map +1 -1
- package/lib/plugins/responseCachePlugin.d.ts +4 -0
- package/lib/plugins/responseCachePlugin.mjs +42 -37
- package/lib/plugins/responseCachePlugin.mjs.map +1 -1
- package/package.json +7 -7
package/lib/plugins/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from './invalidateCachePlugin';
|
|
2
|
-
export
|
|
2
|
+
export { responseCachePlugin } from './responseCachePlugin';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict';var serverCore=require('@common-stack/server-core'),envConfig=require('../config/env-config.cjs');const invalidateCachePlugin = ({ cache: redisClient, invalidateCacheKeyGenerator, }) => ({
|
|
1
|
+
'use strict';var _=require('lodash-es'),serverCore=require('@common-stack/server-core'),envConfig=require('../config/env-config.cjs');const invalidateCachePlugin = ({ cache: redisClient, invalidateCacheKeyGenerator, }) => ({
|
|
2
2
|
requestDidStart(requestContext) {
|
|
3
3
|
return {
|
|
4
4
|
willSendResponse: async (responseContext) => {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
}
|
|
9
9
|
try {
|
|
10
10
|
const hasErrors = !!requestContext.errors?.length;
|
|
11
|
+
const { schema } = requestContext;
|
|
11
12
|
const { queriesToInvalidate, user, req } = requestContext.contextValue;
|
|
12
13
|
const tenantId = serverCore.extractTenantId(req?.currentPageUriSegments?.authority);
|
|
13
14
|
const [{ operation }] = responseContext.document.definitions;
|
|
@@ -17,36 +18,39 @@
|
|
|
17
18
|
}
|
|
18
19
|
const nestedKeys = await Promise.all(queriesToInvalidate.map(async (query) => {
|
|
19
20
|
// Build keys in order of specificity
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
let keys = [];
|
|
22
|
+
const cachePolicy = serverCore.getDirectiveArgsFromSchema({
|
|
23
|
+
schema,
|
|
24
|
+
queryName: query,
|
|
25
|
+
directiveName: serverCore.CACHE_CONTROL_DIRECTIVE,
|
|
26
|
+
});
|
|
27
|
+
const isPrivate = cachePolicy.scope?.toLowerCase() === 'private';
|
|
25
28
|
// Add tenant-specific key if tenant exists
|
|
26
29
|
if (tenantId) {
|
|
27
30
|
keys.push(`${envConfig.config.APP_NAME}:${tenantId}:${query}:*`);
|
|
31
|
+
// Add user-specific key if user exists
|
|
32
|
+
if (user?.sub && isPrivate) {
|
|
33
|
+
keys.push(`${envConfig.config.APP_NAME}:${tenantId}:${user.sub}:${query}:*`);
|
|
34
|
+
}
|
|
28
35
|
}
|
|
29
36
|
// Add global key as fallback
|
|
30
37
|
keys.push(`${envConfig.config.APP_NAME}:${query}:*`);
|
|
31
38
|
// Allow custom key generation if provided
|
|
32
39
|
if (typeof invalidateCacheKeyGenerator === 'function') {
|
|
33
|
-
|
|
34
|
-
if (generatedKey) {
|
|
35
|
-
keys.unshift(generatedKey);
|
|
36
|
-
}
|
|
40
|
+
keys = keys.map((key) => invalidateCacheKeyGenerator(requestContext, responseContext, key));
|
|
37
41
|
}
|
|
38
|
-
|
|
39
|
-
for (const key of keys) {
|
|
42
|
+
const matchedKeys = await Promise.all(keys.map(async (key) => {
|
|
40
43
|
const matchingKeys = await redisClient.keys(key);
|
|
41
44
|
if (matchingKeys.length) {
|
|
42
45
|
return matchingKeys;
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
return [];
|
|
48
|
+
}));
|
|
49
|
+
return matchedKeys.flat();
|
|
46
50
|
}));
|
|
47
51
|
const keys = nestedKeys.flat();
|
|
48
52
|
if (keys?.length) {
|
|
49
|
-
await redisClient.del(keys);
|
|
53
|
+
await redisClient.del(_.uniq(keys));
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invalidateCachePlugin.cjs","sources":["../../src/plugins/invalidateCachePlugin.ts"],"sourcesContent":[null],"names":["extractTenantId","config"],"mappings":"
|
|
1
|
+
{"version":3,"file":"invalidateCachePlugin.cjs","sources":["../../src/plugins/invalidateCachePlugin.ts"],"sourcesContent":[null],"names":["extractTenantId","getDirectiveArgsFromSchema","CACHE_CONTROL_DIRECTIVE","config","uniq"],"mappings":"sIAcO,MAAM,qBAAqB,GAAG,CAAC,EAClC,KAAK,EAAE,WAAW,EAClB,2BAA2B,GAI9B,MACI;AACG,IAAA,eAAe,CAAC,cAA4D,EAAA;QACxE,OAAO;AACH,YAAA,gBAAgB,EAAE,OAAO,eAA+D,KAAI;;gBAExF,IAAI,CAAC,cAAc,EAAE;oBACjB,OAAO;iBACV;AACD,gBAAA,IAAI;oBACA,MAAM,SAAS,GAAG,CAAC,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC;AAClD,oBAAA,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC;oBAClC,MAAM,EAAE,mBAAmB,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,cAAc,CAAC,YAAY,CAAC;oBACvE,MAAM,QAAQ,GAAGA,0BAAe,CAAC,GAAG,EAAE,sBAAsB,EAAE,SAAS,CAAC,CAAC;oBACzE,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC,WAAwC,CAAC;AAC1F,oBAAA,MAAM,UAAU,GAAG,SAAS,KAAK,UAAU,CAAC;oBAC5C,IAAI,SAAS,IAAI,CAAC,mBAAmB,EAAE,MAAM,IAAI,CAAC,UAAU,EAAE;wBAC1D,OAAO;qBACV;AAED,oBAAA,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,mBAAmB,CAAC,GAAG,CAAC,OAAO,KAAa,KAAI;;wBAE5C,IAAI,IAAI,GAAa,EAAE,CAAC;wBACxB,MAAM,WAAW,GAAsBC,qCAA0B,CAAC;4BAC9D,MAAM;AACN,4BAAA,SAAS,EAAE,KAAK;AAChB,4BAAA,aAAa,EAAEC,kCAAuB;AACzC,yBAAA,CAAC,CAAC;wBACH,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,SAAS,CAAC;;wBAEjE,IAAI,QAAQ,EAAE;AACV,4BAAA,IAAI,CAAC,IAAI,CAAC,CAAA,EAAGC,gBAAM,CAAC,QAAQ,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,EAAI,KAAK,CAAA,EAAA,CAAI,CAAC,CAAC;;AAEvD,4BAAA,IAAI,IAAI,EAAE,GAAG,IAAI,SAAS,EAAE;AACxB,gCAAA,IAAI,CAAC,IAAI,CAAC,CAAG,EAAAA,gBAAM,CAAC,QAAQ,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,EAAI,IAAI,CAAC,GAAG,IAAI,KAAK,CAAA,EAAA,CAAI,CAAC,CAAC;6BACtE;yBACJ;;wBAED,IAAI,CAAC,IAAI,CAAC,CAAG,EAAAA,gBAAM,CAAC,QAAQ,CAAI,CAAA,EAAA,KAAK,CAAI,EAAA,CAAA,CAAC,CAAC;;AAG3C,wBAAA,IAAI,OAAO,2BAA2B,KAAK,UAAU,EAAE;AACnD,4BAAA,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,KAChB,2BAA2B,CAAC,cAAc,EAAE,eAAe,EAAE,GAAG,CAAC,CACpE,CAAC;yBACL;AACD,wBAAA,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,KAAI;4BACnB,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjD,4BAAA,IAAI,YAAY,CAAC,MAAM,EAAE;AACrB,gCAAA,OAAO,YAAY,CAAC;6BACvB;AACD,4BAAA,OAAO,EAAE,CAAC;yBACb,CAAC,CACL,CAAC;AACF,wBAAA,OAAO,WAAW,CAAC,IAAI,EAAE,CAAC;qBAC7B,CAAC,CACL,CAAC;AACF,oBAAA,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;AAC/B,oBAAA,IAAI,IAAI,EAAE,MAAM,EAAE;wBACd,MAAM,WAAW,CAAC,GAAG,CAACC,MAAI,CAAC,IAAI,CAAC,CAAC,CAAC;qBACrC;iBACJ;gBAAC,OAAO,CAAC,EAAE;AACR,oBAAA,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;AACvE,oBAAA,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;iBAClC;aACJ;SACJ,CAAC;KACL;AACJ,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {extractTenantId}from'@common-stack/server-core';import {config}from'../config/env-config.mjs';const invalidateCachePlugin = ({ cache: redisClient, invalidateCacheKeyGenerator, }) => ({
|
|
1
|
+
import {uniq}from'lodash-es';import {extractTenantId,getDirectiveArgsFromSchema,CACHE_CONTROL_DIRECTIVE}from'@common-stack/server-core';import {config}from'../config/env-config.mjs';const invalidateCachePlugin = ({ cache: redisClient, invalidateCacheKeyGenerator, }) => ({
|
|
2
2
|
requestDidStart(requestContext) {
|
|
3
3
|
return {
|
|
4
4
|
willSendResponse: async (responseContext) => {
|
|
@@ -8,6 +8,7 @@ import {extractTenantId}from'@common-stack/server-core';import {config}from'../c
|
|
|
8
8
|
}
|
|
9
9
|
try {
|
|
10
10
|
const hasErrors = !!requestContext.errors?.length;
|
|
11
|
+
const { schema } = requestContext;
|
|
11
12
|
const { queriesToInvalidate, user, req } = requestContext.contextValue;
|
|
12
13
|
const tenantId = extractTenantId(req?.currentPageUriSegments?.authority);
|
|
13
14
|
const [{ operation }] = responseContext.document.definitions;
|
|
@@ -17,36 +18,39 @@ import {extractTenantId}from'@common-stack/server-core';import {config}from'../c
|
|
|
17
18
|
}
|
|
18
19
|
const nestedKeys = await Promise.all(queriesToInvalidate.map(async (query) => {
|
|
19
20
|
// Build keys in order of specificity
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
let keys = [];
|
|
22
|
+
const cachePolicy = getDirectiveArgsFromSchema({
|
|
23
|
+
schema,
|
|
24
|
+
queryName: query,
|
|
25
|
+
directiveName: CACHE_CONTROL_DIRECTIVE,
|
|
26
|
+
});
|
|
27
|
+
const isPrivate = cachePolicy.scope?.toLowerCase() === 'private';
|
|
25
28
|
// Add tenant-specific key if tenant exists
|
|
26
29
|
if (tenantId) {
|
|
27
30
|
keys.push(`${config.APP_NAME}:${tenantId}:${query}:*`);
|
|
31
|
+
// Add user-specific key if user exists
|
|
32
|
+
if (user?.sub && isPrivate) {
|
|
33
|
+
keys.push(`${config.APP_NAME}:${tenantId}:${user.sub}:${query}:*`);
|
|
34
|
+
}
|
|
28
35
|
}
|
|
29
36
|
// Add global key as fallback
|
|
30
37
|
keys.push(`${config.APP_NAME}:${query}:*`);
|
|
31
38
|
// Allow custom key generation if provided
|
|
32
39
|
if (typeof invalidateCacheKeyGenerator === 'function') {
|
|
33
|
-
|
|
34
|
-
if (generatedKey) {
|
|
35
|
-
keys.unshift(generatedKey);
|
|
36
|
-
}
|
|
40
|
+
keys = keys.map((key) => invalidateCacheKeyGenerator(requestContext, responseContext, key));
|
|
37
41
|
}
|
|
38
|
-
|
|
39
|
-
for (const key of keys) {
|
|
42
|
+
const matchedKeys = await Promise.all(keys.map(async (key) => {
|
|
40
43
|
const matchingKeys = await redisClient.keys(key);
|
|
41
44
|
if (matchingKeys.length) {
|
|
42
45
|
return matchingKeys;
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
return [];
|
|
48
|
+
}));
|
|
49
|
+
return matchedKeys.flat();
|
|
46
50
|
}));
|
|
47
51
|
const keys = nestedKeys.flat();
|
|
48
52
|
if (keys?.length) {
|
|
49
|
-
await redisClient.del(keys);
|
|
53
|
+
await redisClient.del(uniq(keys));
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invalidateCachePlugin.mjs","sources":["../../src/plugins/invalidateCachePlugin.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"invalidateCachePlugin.mjs","sources":["../../src/plugins/invalidateCachePlugin.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -11,48 +11,53 @@ const isCacheable = (requestContext) => {
|
|
|
11
11
|
if (cache.scope && !cache.maxAge) {
|
|
12
12
|
cache.maxAge = 86400;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
if (!requestContext.overallCachePolicy) {
|
|
15
|
+
// eslint-disable-next-line no-param-reassign
|
|
16
|
+
// to support test cases
|
|
17
|
+
requestContext.overallCachePolicy = {};
|
|
18
|
+
}
|
|
15
19
|
requestContext.overallCachePolicy.maxAge = cache.maxAge;
|
|
16
20
|
return cache.maxAge > 0;
|
|
17
21
|
};
|
|
22
|
+
const generateCacheKey = ({ logger, cacheKeyGenerator }) => (requestContext) => {
|
|
23
|
+
if (!isCacheable(requestContext)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const { request, contextValue, document, schema } = requestContext;
|
|
27
|
+
const { user, req } = contextValue ?? {};
|
|
28
|
+
const { query, variables } = request;
|
|
29
|
+
const cacheControlDirective = serverCore.getDirectiveArgsFromSchema({
|
|
30
|
+
schema,
|
|
31
|
+
document,
|
|
32
|
+
directiveName: serverCore.CACHE_CONTROL_DIRECTIVE,
|
|
33
|
+
});
|
|
34
|
+
const { scope } = cacheControlDirective ?? {};
|
|
35
|
+
const isPrivate = scope?.toLowerCase() === 'private';
|
|
36
|
+
const tenantId = serverCore.extractTenantId(req?.currentPageUriSegments?.authority);
|
|
37
|
+
const cacheKey = serverCore.generateQueryCacheKey({
|
|
38
|
+
query,
|
|
39
|
+
variables,
|
|
40
|
+
logger,
|
|
41
|
+
userId: isPrivate ? user?.sub || null : null,
|
|
42
|
+
tenantId,
|
|
43
|
+
});
|
|
44
|
+
try {
|
|
45
|
+
if (typeof cacheKeyGenerator === 'function') {
|
|
46
|
+
const generatedKey = cacheKeyGenerator(requestContext, cacheKey);
|
|
47
|
+
return generatedKey || cacheKey;
|
|
48
|
+
}
|
|
49
|
+
return cacheKey;
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
// `this.logger` won't work here
|
|
53
|
+
console.warn('GenerateCacheKey Failed %s', e.message);
|
|
54
|
+
return cacheKey;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
18
57
|
const responseCachePlugin = ({ logger, cacheKeyGenerator }) => cachePlugin({
|
|
19
58
|
sessionId: ({ contextValue }) => Promise.resolve(contextValue?.user?.sub ?? null),
|
|
20
|
-
generateCacheKey(
|
|
21
|
-
if (!isCacheable(requestContext)) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
const { request, contextValue, document, schema } = requestContext;
|
|
25
|
-
const { user, req } = contextValue;
|
|
26
|
-
const { query, variables } = request;
|
|
27
|
-
const cacheControlDirective = serverCore.getDirectiveArgsFromSchema({
|
|
28
|
-
schema,
|
|
29
|
-
document,
|
|
30
|
-
directiveName: serverCore.CACHE_CONTROL_DIRECTIVE,
|
|
31
|
-
});
|
|
32
|
-
const { scope } = cacheControlDirective ?? {};
|
|
33
|
-
const isPrivate = scope?.toLowerCase() === 'private';
|
|
34
|
-
const tenantId = serverCore.extractTenantId(req?.currentPageUriSegments?.authority);
|
|
35
|
-
const cacheKey = serverCore.generateQueryCacheKey({
|
|
36
|
-
query,
|
|
37
|
-
variables,
|
|
38
|
-
logger,
|
|
39
|
-
userId: isPrivate ? user?.sub || null : null,
|
|
40
|
-
tenantId,
|
|
41
|
-
});
|
|
42
|
-
try {
|
|
43
|
-
if (typeof cacheKeyGenerator === 'function') {
|
|
44
|
-
const generatedKey = cacheKeyGenerator(requestContext, cacheKey);
|
|
45
|
-
return generatedKey || cacheKey;
|
|
46
|
-
}
|
|
47
|
-
return cacheKey;
|
|
48
|
-
}
|
|
49
|
-
catch (e) {
|
|
50
|
-
// `this.logger` won't work here
|
|
51
|
-
console.warn('GenerateCacheKey Failed %s', e.message);
|
|
52
|
-
return cacheKey;
|
|
53
|
-
}
|
|
54
|
-
},
|
|
59
|
+
generateCacheKey: generateCacheKey({ logger, cacheKeyGenerator }),
|
|
55
60
|
shouldWriteToCache: (ctx) =>
|
|
56
61
|
// Cache only successful responses
|
|
57
62
|
isCacheable(ctx) && _.isEmpty(ctx?.response?.body?.singleResult.errors),
|
|
58
|
-
});exports.responseCachePlugin=responseCachePlugin;//# sourceMappingURL=responseCachePlugin.cjs.map
|
|
63
|
+
});exports.generateCacheKey=generateCacheKey;exports.isCacheable=isCacheable;exports.responseCachePlugin=responseCachePlugin;//# sourceMappingURL=responseCachePlugin.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responseCachePlugin.cjs","sources":["../../src/plugins/responseCachePlugin.ts"],"sourcesContent":[null],"names":["getDirectiveArgsFromSchema","CACHE_CONTROL_DIRECTIVE","extractTenantId","generateQueryCacheKey","isEmpty"],"mappings":"
|
|
1
|
+
{"version":3,"file":"responseCachePlugin.cjs","sources":["../../src/plugins/responseCachePlugin.ts"],"sourcesContent":[null],"names":["getDirectiveArgsFromSchema","CACHE_CONTROL_DIRECTIVE","extractTenantId","generateQueryCacheKey","isEmpty"],"mappings":"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"}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { GraphQLRequestContext } from '@apollo/server';
|
|
1
2
|
import { ILogger } from '@cdm-logger/core/lib/interface';
|
|
3
|
+
import { GraphqlRequestContext } from '../interfaces';
|
|
2
4
|
import { KeyGenerator } from '../servers/GraphqlServer';
|
|
3
5
|
type ApolloCachePluginOptions = {
|
|
4
6
|
logger: ILogger;
|
|
5
7
|
cacheKeyGenerator: KeyGenerator;
|
|
6
8
|
};
|
|
9
|
+
export declare const isCacheable: (requestContext: GraphQLRequestContext<GraphqlRequestContext>) => boolean;
|
|
10
|
+
export declare const generateCacheKey: ({ logger, cacheKeyGenerator }: ApolloCachePluginOptions) => (requestContext: GraphQLRequestContext<GraphqlRequestContext>) => string;
|
|
7
11
|
export declare const responseCachePlugin: ({ logger, cacheKeyGenerator }: ApolloCachePluginOptions) => any;
|
|
8
12
|
export {};
|
|
@@ -11,48 +11,53 @@ const isCacheable = (requestContext) => {
|
|
|
11
11
|
if (cache.scope && !cache.maxAge) {
|
|
12
12
|
cache.maxAge = 86400;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
if (!requestContext.overallCachePolicy) {
|
|
15
|
+
// eslint-disable-next-line no-param-reassign
|
|
16
|
+
// to support test cases
|
|
17
|
+
requestContext.overallCachePolicy = {};
|
|
18
|
+
}
|
|
15
19
|
requestContext.overallCachePolicy.maxAge = cache.maxAge;
|
|
16
20
|
return cache.maxAge > 0;
|
|
17
21
|
};
|
|
22
|
+
const generateCacheKey = ({ logger, cacheKeyGenerator }) => (requestContext) => {
|
|
23
|
+
if (!isCacheable(requestContext)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const { request, contextValue, document, schema } = requestContext;
|
|
27
|
+
const { user, req } = contextValue ?? {};
|
|
28
|
+
const { query, variables } = request;
|
|
29
|
+
const cacheControlDirective = getDirectiveArgsFromSchema({
|
|
30
|
+
schema,
|
|
31
|
+
document,
|
|
32
|
+
directiveName: CACHE_CONTROL_DIRECTIVE,
|
|
33
|
+
});
|
|
34
|
+
const { scope } = cacheControlDirective ?? {};
|
|
35
|
+
const isPrivate = scope?.toLowerCase() === 'private';
|
|
36
|
+
const tenantId = extractTenantId(req?.currentPageUriSegments?.authority);
|
|
37
|
+
const cacheKey = generateQueryCacheKey({
|
|
38
|
+
query,
|
|
39
|
+
variables,
|
|
40
|
+
logger,
|
|
41
|
+
userId: isPrivate ? user?.sub || null : null,
|
|
42
|
+
tenantId,
|
|
43
|
+
});
|
|
44
|
+
try {
|
|
45
|
+
if (typeof cacheKeyGenerator === 'function') {
|
|
46
|
+
const generatedKey = cacheKeyGenerator(requestContext, cacheKey);
|
|
47
|
+
return generatedKey || cacheKey;
|
|
48
|
+
}
|
|
49
|
+
return cacheKey;
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
// `this.logger` won't work here
|
|
53
|
+
console.warn('GenerateCacheKey Failed %s', e.message);
|
|
54
|
+
return cacheKey;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
18
57
|
const responseCachePlugin = ({ logger, cacheKeyGenerator }) => cachePlugin({
|
|
19
58
|
sessionId: ({ contextValue }) => Promise.resolve(contextValue?.user?.sub ?? null),
|
|
20
|
-
generateCacheKey(
|
|
21
|
-
if (!isCacheable(requestContext)) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
const { request, contextValue, document, schema } = requestContext;
|
|
25
|
-
const { user, req } = contextValue;
|
|
26
|
-
const { query, variables } = request;
|
|
27
|
-
const cacheControlDirective = getDirectiveArgsFromSchema({
|
|
28
|
-
schema,
|
|
29
|
-
document,
|
|
30
|
-
directiveName: CACHE_CONTROL_DIRECTIVE,
|
|
31
|
-
});
|
|
32
|
-
const { scope } = cacheControlDirective ?? {};
|
|
33
|
-
const isPrivate = scope?.toLowerCase() === 'private';
|
|
34
|
-
const tenantId = extractTenantId(req?.currentPageUriSegments?.authority);
|
|
35
|
-
const cacheKey = generateQueryCacheKey({
|
|
36
|
-
query,
|
|
37
|
-
variables,
|
|
38
|
-
logger,
|
|
39
|
-
userId: isPrivate ? user?.sub || null : null,
|
|
40
|
-
tenantId,
|
|
41
|
-
});
|
|
42
|
-
try {
|
|
43
|
-
if (typeof cacheKeyGenerator === 'function') {
|
|
44
|
-
const generatedKey = cacheKeyGenerator(requestContext, cacheKey);
|
|
45
|
-
return generatedKey || cacheKey;
|
|
46
|
-
}
|
|
47
|
-
return cacheKey;
|
|
48
|
-
}
|
|
49
|
-
catch (e) {
|
|
50
|
-
// `this.logger` won't work here
|
|
51
|
-
console.warn('GenerateCacheKey Failed %s', e.message);
|
|
52
|
-
return cacheKey;
|
|
53
|
-
}
|
|
54
|
-
},
|
|
59
|
+
generateCacheKey: generateCacheKey({ logger, cacheKeyGenerator }),
|
|
55
60
|
shouldWriteToCache: (ctx) =>
|
|
56
61
|
// Cache only successful responses
|
|
57
62
|
isCacheable(ctx) && isEmpty(ctx?.response?.body?.singleResult.errors),
|
|
58
|
-
});export{responseCachePlugin};//# sourceMappingURL=responseCachePlugin.mjs.map
|
|
63
|
+
});export{generateCacheKey,isCacheable,responseCachePlugin};//# sourceMappingURL=responseCachePlugin.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responseCachePlugin.mjs","sources":["../../src/plugins/responseCachePlugin.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"responseCachePlugin.mjs","sources":["../../src/plugins/responseCachePlugin.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@common-stack/server-stack",
|
|
3
|
-
"version": "7.0.4-alpha.
|
|
3
|
+
"version": "7.0.4-alpha.18",
|
|
4
4
|
"description": "common core for higher packages to depend on",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "CDMBase LLC",
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
"@cdm-logger/client": "^9.0.3",
|
|
32
32
|
"@cdm-logger/server": "^9.0.3",
|
|
33
33
|
"@cdmbase/graphql-type-uri": "^4.0.0",
|
|
34
|
-
"@common-stack/cache-api-server": "7.0.4-alpha.
|
|
35
|
-
"@common-stack/client-core": "7.0.4-alpha.
|
|
36
|
-
"@common-stack/core": "7.0.4-alpha.
|
|
37
|
-
"@common-stack/server-core": "7.0.4-alpha.
|
|
38
|
-
"@common-stack/store-mongo": "7.0.4-alpha.
|
|
34
|
+
"@common-stack/cache-api-server": "7.0.4-alpha.17",
|
|
35
|
+
"@common-stack/client-core": "7.0.4-alpha.17",
|
|
36
|
+
"@common-stack/core": "7.0.4-alpha.17",
|
|
37
|
+
"@common-stack/server-core": "7.0.4-alpha.17",
|
|
38
|
+
"@common-stack/store-mongo": "7.0.4-alpha.17",
|
|
39
39
|
"@graphql-tools/links": "~9.0.1",
|
|
40
40
|
"@graphql-tools/schema": "~10.0.6",
|
|
41
41
|
"@graphql-tools/stitch": "~9.2.10",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"publishConfig": {
|
|
89
89
|
"access": "public"
|
|
90
90
|
},
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "d4a415cafc5fcc96f6b8d39aaccb129b4986edbc",
|
|
92
92
|
"typescript": {
|
|
93
93
|
"definition": "lib/index.d.ts"
|
|
94
94
|
}
|