strapi-cache 1.4.9 → 1.5.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/README.md +3 -1
- package/dist/_chunks/de-CBzKPGsY.mjs +0 -1
- package/dist/_chunks/de-CjN-9Obj.js +0 -1
- package/dist/_chunks/en-BDlRjAzq.mjs +0 -1
- package/dist/_chunks/en-D24wwyGh.js +0 -1
- package/dist/admin/index.js +0 -1
- package/dist/admin/index.mjs +0 -1
- package/dist/server/index.js +24 -7
- package/dist/server/index.mjs +24 -6
- package/dist/server/src/config/index.d.ts +2 -0
- package/dist/server/src/index.d.ts +2 -0
- package/package.json +1 -1
- package/dist/_chunks/de-CBzKPGsY.mjs.map +0 -1
- package/dist/_chunks/de-CjN-9Obj.js.map +0 -1
- package/dist/_chunks/en-BDlRjAzq.mjs.map +0 -1
- package/dist/_chunks/en-D24wwyGh.js.map +0 -1
- package/dist/admin/index.js.map +0 -1
- package/dist/admin/index.mjs.map +0 -1
- package/dist/server/index.js.map +0 -1
- package/dist/server/index.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
**A powerful LRU-Cache plugin for Strapi v5**
|
|
4
4
|
Boost your API performance with automatic in-memory or Redis caching for REST and GraphQL requests.
|
|
5
5
|
|
|
6
|
-

|
|
7
7
|

|
|
8
8
|

|
|
9
9
|

|
|
@@ -52,6 +52,8 @@ In your Strapi project, navigate to `config/plugins.js` and add the following co
|
|
|
52
52
|
cacheableRoutes: ['/api/products', '/api/categories'], // Caches routes which start with these paths (if empty array, all '/api' routes are cached)
|
|
53
53
|
provider: 'memory', // Cache provider ('memory' or 'redis')
|
|
54
54
|
redisConfig: env('REDIS_URL', 'redis://localhost:6379'), // Redis config takes either a string or an object see https://ioredis.readthedocs.io/en/stable/README for references to what object is available, the object or string is passed directly to ioredis client (if using Redis)
|
|
55
|
+
redisClusterNodes: [], // If provided any cluster node (this list is not empty), initialize ioredis redis cluster client. Each object must have keys 'host' and 'port'. See https://ioredis.readthedocs.io/en/stable/README for references
|
|
56
|
+
redisClusterOptions: {}, // Options for ioredis redis cluster client. redisOptions key is taken from redisConfig parameter above if not set here. See https://ioredis.readthedocs.io/en/stable/README for references
|
|
55
57
|
cacheHeaders: true, // Plugin also stores response headers in the cache (set to false if you don't want to cache headers)
|
|
56
58
|
cacheAuthorizedRequests: false, // Cache requests with authorization headers (set to true if you want to cache authorized requests)
|
|
57
59
|
cacheGetTimeoutInMs: 1000, // Timeout for getting cached data in milliseconds (default is 1 seconds)
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -4,11 +4,10 @@ const Stream = require("stream");
|
|
|
4
4
|
const zlib = require("zlib");
|
|
5
5
|
const rawBody = require("raw-body");
|
|
6
6
|
const lruCache = require("lru-cache");
|
|
7
|
-
const
|
|
7
|
+
const ioredis = require("ioredis");
|
|
8
8
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
9
9
|
const Stream__default = /* @__PURE__ */ _interopDefault(Stream);
|
|
10
10
|
const rawBody__default = /* @__PURE__ */ _interopDefault(rawBody);
|
|
11
|
-
const Redis__default = /* @__PURE__ */ _interopDefault(Redis);
|
|
12
11
|
const loggy = {
|
|
13
12
|
info: (msg) => {
|
|
14
13
|
const shouldDebug = strapi.plugin("strapi-cache").config("debug") ?? false;
|
|
@@ -277,6 +276,8 @@ const config = {
|
|
|
277
276
|
cacheableRoutes: [],
|
|
278
277
|
provider: "memory",
|
|
279
278
|
redisConfig: env("REDIS_URL"),
|
|
279
|
+
redisClusterNodes: [],
|
|
280
|
+
redisClusterOptions: {},
|
|
280
281
|
cacheHeaders: true,
|
|
281
282
|
cacheAuthorizedRequests: false,
|
|
282
283
|
cacheGetTimeoutInMs: 1e3
|
|
@@ -306,8 +307,16 @@ const config = {
|
|
|
306
307
|
if (config2.provider !== "memory" && config2.provider !== "redis") {
|
|
307
308
|
throw new Error(`Invalid config: provider must be 'memory' or 'redis'`);
|
|
308
309
|
}
|
|
309
|
-
if (config2.provider === "redis"
|
|
310
|
-
|
|
310
|
+
if (config2.provider === "redis") {
|
|
311
|
+
if (!config2.redisConfig && (typeof config2.redisConfig !== "string" || typeof config2.redisConfig !== "object")) {
|
|
312
|
+
throw new Error(`Invalid config: redisConfig must be set when using redis provider`);
|
|
313
|
+
}
|
|
314
|
+
if (!Array.isArray(config2.redisClusterNodes) || config2.redisClusterNodes.some((item) => !("host" in item && "port" in item))) {
|
|
315
|
+
throw new Error(`Invalid config: redisClusterNodes must be as a list of objects with keys 'host' and 'port'`);
|
|
316
|
+
}
|
|
317
|
+
if (typeof config2.redisClusterOptions !== "object") {
|
|
318
|
+
throw new Error(`Invalid config: redisClusterOptions must be an object`);
|
|
319
|
+
}
|
|
311
320
|
}
|
|
312
321
|
if (typeof config2.cacheHeaders !== "boolean") {
|
|
313
322
|
throw new Error(`Invalid config: cacheHeaders must be a boolean`);
|
|
@@ -522,11 +531,20 @@ class RedisCacheProvider {
|
|
|
522
531
|
return;
|
|
523
532
|
}
|
|
524
533
|
try {
|
|
525
|
-
const
|
|
534
|
+
const redisConfig = this.strapi.plugin("strapi-cache").config("redisConfig") || "redis://localhost:6379";
|
|
535
|
+
const redisClusterNodes = this.strapi.plugin("strapi-cache").config("redisClusterNodes");
|
|
526
536
|
this.cacheGetTimeoutInMs = Number(
|
|
527
537
|
this.strapi.plugin("strapi-cache").config("cacheGetTimeoutInMs")
|
|
528
538
|
);
|
|
529
|
-
|
|
539
|
+
if (redisClusterNodes.length) {
|
|
540
|
+
const redisClusterOptions = this.strapi.plugin("strapi-cache").config("redisClusterOptions");
|
|
541
|
+
if (!redisClusterOptions["redisOptions"]) {
|
|
542
|
+
redisClusterOptions.redisOptions = redisConfig;
|
|
543
|
+
}
|
|
544
|
+
this.client = new ioredis.Redis.Cluster(redisClusterNodes, redisClusterOptions);
|
|
545
|
+
} else {
|
|
546
|
+
this.client = new ioredis.Redis(redisConfig);
|
|
547
|
+
}
|
|
530
548
|
this.initialized = true;
|
|
531
549
|
loggy.info("Redis provider initialized");
|
|
532
550
|
} catch (error) {
|
|
@@ -645,4 +663,3 @@ const index = {
|
|
|
645
663
|
middlewares
|
|
646
664
|
};
|
|
647
665
|
module.exports = index;
|
|
648
|
-
//# sourceMappingURL=index.js.map
|
package/dist/server/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import Stream, { Readable } from "stream";
|
|
|
3
3
|
import { createInflate, createBrotliDecompress, createGunzip } from "zlib";
|
|
4
4
|
import rawBody from "raw-body";
|
|
5
5
|
import { LRUCache } from "lru-cache";
|
|
6
|
-
import Redis from "ioredis";
|
|
6
|
+
import { Redis } from "ioredis";
|
|
7
7
|
const loggy = {
|
|
8
8
|
info: (msg) => {
|
|
9
9
|
const shouldDebug = strapi.plugin("strapi-cache").config("debug") ?? false;
|
|
@@ -272,6 +272,8 @@ const config = {
|
|
|
272
272
|
cacheableRoutes: [],
|
|
273
273
|
provider: "memory",
|
|
274
274
|
redisConfig: env("REDIS_URL"),
|
|
275
|
+
redisClusterNodes: [],
|
|
276
|
+
redisClusterOptions: {},
|
|
275
277
|
cacheHeaders: true,
|
|
276
278
|
cacheAuthorizedRequests: false,
|
|
277
279
|
cacheGetTimeoutInMs: 1e3
|
|
@@ -301,8 +303,16 @@ const config = {
|
|
|
301
303
|
if (config2.provider !== "memory" && config2.provider !== "redis") {
|
|
302
304
|
throw new Error(`Invalid config: provider must be 'memory' or 'redis'`);
|
|
303
305
|
}
|
|
304
|
-
if (config2.provider === "redis"
|
|
305
|
-
|
|
306
|
+
if (config2.provider === "redis") {
|
|
307
|
+
if (!config2.redisConfig && (typeof config2.redisConfig !== "string" || typeof config2.redisConfig !== "object")) {
|
|
308
|
+
throw new Error(`Invalid config: redisConfig must be set when using redis provider`);
|
|
309
|
+
}
|
|
310
|
+
if (!Array.isArray(config2.redisClusterNodes) || config2.redisClusterNodes.some((item) => !("host" in item && "port" in item))) {
|
|
311
|
+
throw new Error(`Invalid config: redisClusterNodes must be as a list of objects with keys 'host' and 'port'`);
|
|
312
|
+
}
|
|
313
|
+
if (typeof config2.redisClusterOptions !== "object") {
|
|
314
|
+
throw new Error(`Invalid config: redisClusterOptions must be an object`);
|
|
315
|
+
}
|
|
306
316
|
}
|
|
307
317
|
if (typeof config2.cacheHeaders !== "boolean") {
|
|
308
318
|
throw new Error(`Invalid config: cacheHeaders must be a boolean`);
|
|
@@ -517,11 +527,20 @@ class RedisCacheProvider {
|
|
|
517
527
|
return;
|
|
518
528
|
}
|
|
519
529
|
try {
|
|
520
|
-
const
|
|
530
|
+
const redisConfig = this.strapi.plugin("strapi-cache").config("redisConfig") || "redis://localhost:6379";
|
|
531
|
+
const redisClusterNodes = this.strapi.plugin("strapi-cache").config("redisClusterNodes");
|
|
521
532
|
this.cacheGetTimeoutInMs = Number(
|
|
522
533
|
this.strapi.plugin("strapi-cache").config("cacheGetTimeoutInMs")
|
|
523
534
|
);
|
|
524
|
-
|
|
535
|
+
if (redisClusterNodes.length) {
|
|
536
|
+
const redisClusterOptions = this.strapi.plugin("strapi-cache").config("redisClusterOptions");
|
|
537
|
+
if (!redisClusterOptions["redisOptions"]) {
|
|
538
|
+
redisClusterOptions.redisOptions = redisConfig;
|
|
539
|
+
}
|
|
540
|
+
this.client = new Redis.Cluster(redisClusterNodes, redisClusterOptions);
|
|
541
|
+
} else {
|
|
542
|
+
this.client = new Redis(redisConfig);
|
|
543
|
+
}
|
|
525
544
|
this.initialized = true;
|
|
526
545
|
loggy.info("Redis provider initialized");
|
|
527
546
|
} catch (error) {
|
|
@@ -642,4 +661,3 @@ const index = {
|
|
|
642
661
|
export {
|
|
643
662
|
index as default
|
|
644
663
|
};
|
|
645
|
-
//# sourceMappingURL=index.mjs.map
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"de-CBzKPGsY.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"de-CjN-9Obj.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"en-BDlRjAzq.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"en-D24wwyGh.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
|
package/dist/admin/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../admin/src/pluginId.ts","../../admin/src/components/Initializer.tsx","../../admin/src/permission.ts","../../admin/src/components/PurgeModal/PurgeButton/index.tsx","../../admin/src/components/PurgeModal/index.tsx","../../admin/src/components/PurgeCacheButton/index.tsx","../../admin/src/components/PurgeEntityButton/index.tsx","../../admin/src/index.ts"],"sourcesContent":["export const PLUGIN_ID = 'strapi-cache';\n","import { useEffect, useRef } from 'react';\n\nimport { PLUGIN_ID } from '../pluginId';\n\ntype InitializerProps = {\n setPlugin: (id: string) => void;\n};\n\nconst Initializer = ({ setPlugin }: InitializerProps) => {\n const ref = useRef(setPlugin);\n\n useEffect(() => {\n ref.current(PLUGIN_ID);\n }, []);\n\n return null;\n};\n\nexport { Initializer };\n","export const pluginPermissions = {\n purge: [{ action: 'plugin::strapi-cache.purge-cache', subject: null }],\n};\n","import { Button } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nfunction PurgeButton({ onClick }: { onClick: () => void }) {\n const formatMessage = useIntl().formatMessage;\n\n return (\n <Button onClick={onClick}>\n {formatMessage({\n id: 'strapi-cache.cache.confirm',\n defaultMessage: 'Yes, confirm',\n })}\n </Button>\n );\n}\n\nexport default PurgeButton;\n","import { useIntl } from 'react-intl';\nimport { Archive } from '@strapi/icons';\nimport { Button, Modal } from '@strapi/design-system';\nimport { useNotification, useRBAC } from '@strapi/strapi/admin';\nimport { pluginPermissions } from '../../permission';\nimport { Typography } from '@strapi/design-system';\nimport { useFetchClient } from '@strapi/strapi/admin';\nimport { useEffect, useState } from 'react';\nimport PurgeButton from './PurgeButton';\n\nexport type PurgeProps = {\n buttonText: string;\n buttonWidth?: string;\n keyToUse?: string;\n contentTypeName?: string;\n};\n\nfunction PurgeModal({ buttonText, keyToUse, buttonWidth, contentTypeName }: PurgeProps) {\n const { allowedActions } = useRBAC(pluginPermissions);\n const formatMessage = useIntl().formatMessage;\n const { post, get } = useFetchClient();\n const { toggleNotification } = useNotification();\n const [cacheableRoutes, setCacheableRoutes] = useState<string[]>();\n\n useEffect(() => {\n if (!allowedActions.canPurgeCache) {\n return;\n }\n const fetchCacheableRoutes = async () => {\n try {\n const { data } = await get('/strapi-cache/cacheable-routes');\n return data;\n } catch (error) {\n console.error('Error fetching cacheable routes:', error);\n return undefined;\n }\n };\n fetchCacheableRoutes().then((data) => {\n setCacheableRoutes(data);\n });\n }, [allowedActions.canPurgeCache]);\n\n const isCacheableRoute = () => {\n if (!keyToUse || !cacheableRoutes) {\n return false;\n }\n\n return (\n cacheableRoutes.length === 0 ||\n cacheableRoutes.some((route) => {\n return route.includes(keyToUse) || (contentTypeName && route.includes(contentTypeName));\n })\n );\n };\n\n const clearCache = () => {\n if (!keyToUse) {\n toggleNotification({\n type: 'warning',\n message: formatMessage({\n id: 'strapi-cache.cache.purge.no-content-type',\n defaultMessage: 'No content type found',\n }),\n });\n return;\n }\n\n post(`/strapi-cache/purge-cache/${keyToUse}`, undefined, {\n headers: {\n 'Content-Type': 'application/json',\n },\n })\n .then(() => {\n toggleNotification({\n type: 'success',\n message: formatMessage(\n {\n id: 'strapi-cache.cache.purge.success',\n defaultMessage: 'Cache purged successfully',\n },\n {\n key: `\"${keyToUse}\"`,\n }\n ),\n });\n })\n .catch(() => {\n toggleNotification({\n type: 'danger',\n message: formatMessage(\n {\n id: 'strapi-cache.cache.purge.error',\n defaultMessage: 'Error purging cache',\n },\n {\n key: `\"${keyToUse}\"`,\n }\n ),\n });\n });\n };\n\n if (!allowedActions.canPurgeCache || !isCacheableRoute()) {\n return null;\n }\n\n return (\n <Modal.Root>\n <Modal.Trigger>\n <Button width={buttonWidth} startIcon={<Archive />} variant=\"danger\">\n {buttonText}\n </Button>\n </Modal.Trigger>\n <Modal.Content>\n <Modal.Header>\n <Modal.Title>{buttonText}</Modal.Title>\n </Modal.Header>\n <Modal.Body>\n <Typography variant=\"omega\">\n {formatMessage(\n {\n id: 'strapi-cache.cache.purge.confirmation',\n defaultMessage: 'Are you sure you want to purge the cache?',\n },\n { key: `\"${keyToUse}\"` }\n )}\n </Typography>\n </Modal.Body>\n <Modal.Footer>\n <Modal.Close>\n <Button variant=\"tertiary\">\n {formatMessage({\n id: 'strapi-cache.cache.cancel',\n defaultMessage: 'No, cancel',\n })}\n </Button>\n </Modal.Close>\n <Modal.Close>\n <PurgeButton onClick={clearCache}></PurgeButton>\n </Modal.Close>\n </Modal.Footer>\n </Modal.Content>\n </Modal.Root>\n );\n}\n\nexport default PurgeModal;\n","import { unstable_useContentManagerContext as useContentManagerContext } from '@strapi/strapi/admin';\nimport PurgeModal from '../PurgeModal';\nimport { useIntl } from 'react-intl';\n\nfunction PurgeCacheButton() {\n const { contentType } = useContentManagerContext();\n const { formatMessage } = useIntl();\n const keyToUse = contentType?.info.pluralName;\n\n return (\n <PurgeModal\n buttonText={formatMessage({\n id: 'strapi-cache.cache.purge',\n defaultMessage: 'Purge Cache',\n })}\n keyToUse={keyToUse}\n ></PurgeModal>\n );\n}\n\nexport default PurgeCacheButton;\n","import { unstable_useContentManagerContext as useContentManagerContext } from '@strapi/strapi/admin';\nimport PurgeModal from '../PurgeModal';\nimport { useIntl } from 'react-intl';\n\nfunction PurgeEntityButton() {\n const { formatMessage } = useIntl();\n const { id, isSingleType, contentType } = useContentManagerContext();\n const keyToUse = isSingleType ? contentType?.info.singularName : id;\n const contentTypeName = isSingleType\n ? contentType?.info.singularName\n : contentType?.info.pluralName;\n\n return (\n <PurgeModal\n buttonWidth=\"100%\"\n buttonText={formatMessage({\n id: 'strapi-cache.cache.purge.entity',\n defaultMessage: 'Purge Entity Cache',\n })}\n keyToUse={keyToUse}\n contentTypeName={contentTypeName}\n ></PurgeModal>\n );\n}\n\nexport default PurgeEntityButton;\n","import { PLUGIN_ID } from './pluginId';\nimport { Initializer } from './components/Initializer';\nimport PurgeCacheButton from './components/PurgeCacheButton';\nimport PurgeEntityButton from './components/PurgeEntityButton';\n\nexport default {\n register(app: any) {\n app.registerPlugin({\n id: PLUGIN_ID,\n initializer: Initializer,\n isReady: false,\n name: PLUGIN_ID,\n });\n\n app.getPlugin('content-manager').injectComponent('listView', 'actions', {\n name: PurgeCacheButton,\n Component: PurgeCacheButton,\n });\n\n app.getPlugin('content-manager').injectComponent('editView', 'right-links', {\n name: PurgeEntityButton,\n Component: PurgeEntityButton,\n });\n },\n\n async registerTrads({ locales }: { locales: string[] }) {\n return Promise.all(\n locales.map(async (locale) => {\n try {\n const { default: data } = await import(`./translations/${locale}.json`);\n\n return { data, locale };\n } catch {\n return { data: {}, locale };\n }\n })\n );\n },\n};\n"],"names":["useRef","useEffect","useIntl","jsx","Button","useRBAC","useFetchClient","useNotification","useState","jsxs","Modal","Archive","Typography","useContentManagerContext"],"mappings":"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"}
|
package/dist/admin/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../admin/src/pluginId.ts","../../admin/src/components/Initializer.tsx","../../admin/src/permission.ts","../../admin/src/components/PurgeModal/PurgeButton/index.tsx","../../admin/src/components/PurgeModal/index.tsx","../../admin/src/components/PurgeCacheButton/index.tsx","../../admin/src/components/PurgeEntityButton/index.tsx","../../admin/src/index.ts"],"sourcesContent":["export const PLUGIN_ID = 'strapi-cache';\n","import { useEffect, useRef } from 'react';\n\nimport { PLUGIN_ID } from '../pluginId';\n\ntype InitializerProps = {\n setPlugin: (id: string) => void;\n};\n\nconst Initializer = ({ setPlugin }: InitializerProps) => {\n const ref = useRef(setPlugin);\n\n useEffect(() => {\n ref.current(PLUGIN_ID);\n }, []);\n\n return null;\n};\n\nexport { Initializer };\n","export const pluginPermissions = {\n purge: [{ action: 'plugin::strapi-cache.purge-cache', subject: null }],\n};\n","import { Button } from '@strapi/design-system';\nimport { useIntl } from 'react-intl';\n\nfunction PurgeButton({ onClick }: { onClick: () => void }) {\n const formatMessage = useIntl().formatMessage;\n\n return (\n <Button onClick={onClick}>\n {formatMessage({\n id: 'strapi-cache.cache.confirm',\n defaultMessage: 'Yes, confirm',\n })}\n </Button>\n );\n}\n\nexport default PurgeButton;\n","import { useIntl } from 'react-intl';\nimport { Archive } from '@strapi/icons';\nimport { Button, Modal } from '@strapi/design-system';\nimport { useNotification, useRBAC } from '@strapi/strapi/admin';\nimport { pluginPermissions } from '../../permission';\nimport { Typography } from '@strapi/design-system';\nimport { useFetchClient } from '@strapi/strapi/admin';\nimport { useEffect, useState } from 'react';\nimport PurgeButton from './PurgeButton';\n\nexport type PurgeProps = {\n buttonText: string;\n buttonWidth?: string;\n keyToUse?: string;\n contentTypeName?: string;\n};\n\nfunction PurgeModal({ buttonText, keyToUse, buttonWidth, contentTypeName }: PurgeProps) {\n const { allowedActions } = useRBAC(pluginPermissions);\n const formatMessage = useIntl().formatMessage;\n const { post, get } = useFetchClient();\n const { toggleNotification } = useNotification();\n const [cacheableRoutes, setCacheableRoutes] = useState<string[]>();\n\n useEffect(() => {\n if (!allowedActions.canPurgeCache) {\n return;\n }\n const fetchCacheableRoutes = async () => {\n try {\n const { data } = await get('/strapi-cache/cacheable-routes');\n return data;\n } catch (error) {\n console.error('Error fetching cacheable routes:', error);\n return undefined;\n }\n };\n fetchCacheableRoutes().then((data) => {\n setCacheableRoutes(data);\n });\n }, [allowedActions.canPurgeCache]);\n\n const isCacheableRoute = () => {\n if (!keyToUse || !cacheableRoutes) {\n return false;\n }\n\n return (\n cacheableRoutes.length === 0 ||\n cacheableRoutes.some((route) => {\n return route.includes(keyToUse) || (contentTypeName && route.includes(contentTypeName));\n })\n );\n };\n\n const clearCache = () => {\n if (!keyToUse) {\n toggleNotification({\n type: 'warning',\n message: formatMessage({\n id: 'strapi-cache.cache.purge.no-content-type',\n defaultMessage: 'No content type found',\n }),\n });\n return;\n }\n\n post(`/strapi-cache/purge-cache/${keyToUse}`, undefined, {\n headers: {\n 'Content-Type': 'application/json',\n },\n })\n .then(() => {\n toggleNotification({\n type: 'success',\n message: formatMessage(\n {\n id: 'strapi-cache.cache.purge.success',\n defaultMessage: 'Cache purged successfully',\n },\n {\n key: `\"${keyToUse}\"`,\n }\n ),\n });\n })\n .catch(() => {\n toggleNotification({\n type: 'danger',\n message: formatMessage(\n {\n id: 'strapi-cache.cache.purge.error',\n defaultMessage: 'Error purging cache',\n },\n {\n key: `\"${keyToUse}\"`,\n }\n ),\n });\n });\n };\n\n if (!allowedActions.canPurgeCache || !isCacheableRoute()) {\n return null;\n }\n\n return (\n <Modal.Root>\n <Modal.Trigger>\n <Button width={buttonWidth} startIcon={<Archive />} variant=\"danger\">\n {buttonText}\n </Button>\n </Modal.Trigger>\n <Modal.Content>\n <Modal.Header>\n <Modal.Title>{buttonText}</Modal.Title>\n </Modal.Header>\n <Modal.Body>\n <Typography variant=\"omega\">\n {formatMessage(\n {\n id: 'strapi-cache.cache.purge.confirmation',\n defaultMessage: 'Are you sure you want to purge the cache?',\n },\n { key: `\"${keyToUse}\"` }\n )}\n </Typography>\n </Modal.Body>\n <Modal.Footer>\n <Modal.Close>\n <Button variant=\"tertiary\">\n {formatMessage({\n id: 'strapi-cache.cache.cancel',\n defaultMessage: 'No, cancel',\n })}\n </Button>\n </Modal.Close>\n <Modal.Close>\n <PurgeButton onClick={clearCache}></PurgeButton>\n </Modal.Close>\n </Modal.Footer>\n </Modal.Content>\n </Modal.Root>\n );\n}\n\nexport default PurgeModal;\n","import { unstable_useContentManagerContext as useContentManagerContext } from '@strapi/strapi/admin';\nimport PurgeModal from '../PurgeModal';\nimport { useIntl } from 'react-intl';\n\nfunction PurgeCacheButton() {\n const { contentType } = useContentManagerContext();\n const { formatMessage } = useIntl();\n const keyToUse = contentType?.info.pluralName;\n\n return (\n <PurgeModal\n buttonText={formatMessage({\n id: 'strapi-cache.cache.purge',\n defaultMessage: 'Purge Cache',\n })}\n keyToUse={keyToUse}\n ></PurgeModal>\n );\n}\n\nexport default PurgeCacheButton;\n","import { unstable_useContentManagerContext as useContentManagerContext } from '@strapi/strapi/admin';\nimport PurgeModal from '../PurgeModal';\nimport { useIntl } from 'react-intl';\n\nfunction PurgeEntityButton() {\n const { formatMessage } = useIntl();\n const { id, isSingleType, contentType } = useContentManagerContext();\n const keyToUse = isSingleType ? contentType?.info.singularName : id;\n const contentTypeName = isSingleType\n ? contentType?.info.singularName\n : contentType?.info.pluralName;\n\n return (\n <PurgeModal\n buttonWidth=\"100%\"\n buttonText={formatMessage({\n id: 'strapi-cache.cache.purge.entity',\n defaultMessage: 'Purge Entity Cache',\n })}\n keyToUse={keyToUse}\n contentTypeName={contentTypeName}\n ></PurgeModal>\n );\n}\n\nexport default PurgeEntityButton;\n","import { PLUGIN_ID } from './pluginId';\nimport { Initializer } from './components/Initializer';\nimport PurgeCacheButton from './components/PurgeCacheButton';\nimport PurgeEntityButton from './components/PurgeEntityButton';\n\nexport default {\n register(app: any) {\n app.registerPlugin({\n id: PLUGIN_ID,\n initializer: Initializer,\n isReady: false,\n name: PLUGIN_ID,\n });\n\n app.getPlugin('content-manager').injectComponent('listView', 'actions', {\n name: PurgeCacheButton,\n Component: PurgeCacheButton,\n });\n\n app.getPlugin('content-manager').injectComponent('editView', 'right-links', {\n name: PurgeEntityButton,\n Component: PurgeEntityButton,\n });\n },\n\n async registerTrads({ locales }: { locales: string[] }) {\n return Promise.all(\n locales.map(async (locale) => {\n try {\n const { default: data } = await import(`./translations/${locale}.json`);\n\n return { data, locale };\n } catch {\n return { data: {}, locale };\n }\n })\n );\n },\n};\n"],"names":["useContentManagerContext"],"mappings":"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"}
|
package/dist/server/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../server/src/utils/log.ts","../../server/src/utils/invalidateCache.ts","../../server/src/permissions.ts","../../server/src/bootstrap.ts","../../server/src/utils/key.ts","../../server/src/utils/body.ts","../../server/src/middlewares/cache.ts","../../server/src/middlewares/graphql.ts","../../server/src/middlewares/index.ts","../../server/src/register.ts","../../server/src/config/index.ts","../../server/src/content-types/index.ts","../../server/src/controllers/controller.ts","../../server/src/controllers/index.ts","../../server/src/policies/index.ts","../../server/src/routes/purge.ts","../../server/src/routes/index.ts","../../server/src/utils/withTimeout.ts","../../server/src/services/memory/provider.ts","../../server/src/services/redis/provider.ts","../../server/src/services/resolver.ts","../../server/src/services/index.ts","../../server/src/index.ts"],"sourcesContent":["export const loggy = {\n info: (msg: string) => {\n const shouldDebug = strapi.plugin('strapi-cache').config('debug') ?? false;\n if (!shouldDebug) {\n return;\n }\n strapi.log.info(`[STRAPI CACHE] ${msg}`);\n },\n error: (msg: string) => {\n const shouldDebug = strapi.plugin('strapi-cache').config('debug') ?? false;\n if (!shouldDebug) {\n return;\n }\n strapi.log.error(`[STRAPI CACHE] ${msg}`);\n },\n warn: (msg: string) => {\n const shouldDebug = strapi.plugin('strapi-cache').config('debug') ?? false;\n if (!shouldDebug) {\n return;\n }\n strapi.log.warn(`[STRAPI CACHE] ${msg}`);\n },\n};\n","import { Core } from '@strapi/strapi';\nimport { CacheProvider } from 'src/types/cache.types';\nimport { loggy } from './log';\n\nexport async function invalidateCache(event: any, cacheStore: CacheProvider, strapi: Core.Strapi) {\n const { model } = event;\n const uid = model.uid;\n\n try {\n const contentType = strapi.contentType(uid);\n\n if (!contentType || !contentType.kind) {\n loggy.info(`Content type ${uid} not found`);\n return;\n }\n\n const pluralName =\n contentType.kind === 'singleType'\n ? contentType.info.singularName\n : contentType.info.pluralName;\n const apiPath = `/api/${pluralName}`;\n const regex = new RegExp(`^.*:${apiPath}(/.*)?(\\\\?.*)?$`);\n\n await cacheStore.clearByRegexp([regex]);\n loggy.info(`Invalidated cache for ${apiPath}`);\n } catch (error) {\n loggy.error('Cache invalidation error:');\n loggy.error(error);\n }\n}\n\nexport async function invalidateGraphqlCache(\n event: any,\n cacheStore: CacheProvider,\n strapi: Core.Strapi\n) {\n try {\n const graphqlRegex = new RegExp(`^POST:\\/graphql(:.*)?$`);\n\n await cacheStore.clearByRegexp([graphqlRegex]);\n loggy.info(`Invalidated cache for ${graphqlRegex}`);\n } catch (error) {\n loggy.error('Cache invalidation error:');\n loggy.error(error);\n }\n}\n","export const actions = [\n {\n section: 'plugins',\n displayName: 'Purge Cache',\n uid: 'purge-cache',\n pluginName: 'strapi-cache',\n },\n];\n","import type { Core } from '@strapi/strapi';\nimport { invalidateCache, invalidateGraphqlCache } from './utils/invalidateCache';\nimport { CacheService } from './types/cache.types';\nimport { loggy } from './utils/log';\nimport { actions } from './permissions';\n\nconst bootstrap = ({ strapi }: { strapi: Core.Strapi }) => {\n loggy.info('Initializing');\n try {\n const cacheService = strapi.plugin('strapi-cache').services.service as CacheService;\n const cacheStore = cacheService.getCacheInstance();\n cacheStore.init();\n\n strapi.db.lifecycles.subscribe({\n async afterCreate(event) {\n await invalidateCache(event, cacheStore, strapi);\n await invalidateGraphqlCache(event, cacheStore, strapi);\n },\n async afterUpdate(event) {\n await invalidateCache(event, cacheStore, strapi);\n await invalidateGraphqlCache(event, cacheStore, strapi);\n },\n async afterDelete(event) {\n await invalidateCache(event, cacheStore, strapi);\n await invalidateGraphqlCache(event, cacheStore, strapi);\n },\n });\n\n if (!cacheStore) {\n loggy.error('Plugin could not be initialized');\n return;\n }\n } catch (error) {\n loggy.error('Plugin could not be initialized');\n return;\n }\n loggy.info('Plugin initialized');\n\n strapi.admin.services.permission.actionProvider.registerMany(actions);\n};\n\nexport default bootstrap;\n","import { createHash } from 'crypto';\nimport { Context } from 'koa';\n\nexport const generateCacheKey = (context: Context) => {\n const { url } = context.request;\n const { method } = context.request;\n\n return `${method}:${url}`;\n};\n\nexport const generateGraphqlCacheKey = (payload: string) => {\n const hash = createHash('sha256').update(payload).digest('base64url');\n return `POST:/graphql:${hash}`;\n};\n","import { Stream } from 'stream';\nimport { createGunzip, createBrotliDecompress, createInflate } from 'zlib';\n\nexport const streamToBuffer = (stream: Stream): Promise<Buffer> => {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n stream.on('data', (chunk) => chunks.push(chunk));\n stream.on('end', () => resolve(Buffer.concat(chunks)));\n stream.on('error', reject);\n });\n};\n\nexport const decompressBuffer = async (buffer: Buffer, encoding?: string): Promise<Buffer> => {\n return new Promise((resolve, reject) => {\n let decompressStream;\n switch (encoding) {\n case 'gzip':\n decompressStream = createGunzip();\n break;\n case 'br':\n decompressStream = createBrotliDecompress();\n break;\n case 'deflate':\n decompressStream = createInflate();\n break;\n default:\n return resolve(buffer);\n }\n\n const chunks: Buffer[] = [];\n decompressStream.on('data', (chunk) => chunks.push(chunk));\n decompressStream.on('end', () => resolve(Buffer.concat(chunks)));\n decompressStream.on('error', reject);\n\n decompressStream.end(buffer);\n });\n};\n\nexport const decodeBufferToText = (buffer: Buffer): string => {\n const decoder = new TextDecoder('utf-8');\n return decoder.decode(buffer);\n};\n","import { Context } from 'koa';\nimport { generateCacheKey } from '../utils/key';\nimport { CacheService } from '../../src/types/cache.types';\nimport { loggy } from '../utils/log';\nimport Stream from 'stream';\nimport { decodeBufferToText, decompressBuffer, streamToBuffer } from '../../src/utils/body';\n\nconst middleware = async (ctx: Context, next: any) => {\n const cacheService = strapi.plugin('strapi-cache').services.service as CacheService;\n const cacheableRoutes = strapi.plugin('strapi-cache').config('cacheableRoutes') as string[];\n const cacheHeaders = strapi.plugin('strapi-cache').config('cacheHeaders') as boolean;\n const cacheAuthorizedRequests = strapi\n .plugin('strapi-cache')\n .config('cacheAuthorizedRequests') as boolean;\n const cacheStore = cacheService.getCacheInstance();\n const { url } = ctx.request;\n const key = generateCacheKey(ctx);\n const cacheEntry = await cacheStore.get(key);\n const cacheControlHeader = ctx.request.headers['cache-control'];\n const noCache = cacheControlHeader && cacheControlHeader.includes('no-cache');\n const routeIsCachable =\n cacheableRoutes.some((route) => url.startsWith(route)) ||\n (cacheableRoutes.length === 0 && url.startsWith('/api'));\n const authorizationHeader = ctx.request.headers['authorization'];\n\n if (authorizationHeader && !cacheAuthorizedRequests) {\n loggy.info(`Authorized request bypassing cache: ${key}`);\n await next();\n return;\n }\n\n if (cacheEntry && !noCache) {\n loggy.info(`HIT with key: ${key}`);\n ctx.status = 200;\n ctx.body = cacheEntry.body;\n if (cacheHeaders) {\n ctx.set(cacheEntry.headers);\n }\n return;\n }\n\n await next();\n\n if (ctx.method === 'GET' && ctx.status >= 200 && ctx.status < 300 && routeIsCachable) {\n loggy.info(`MISS with key: ${key}`);\n\n if (ctx.body instanceof Stream) {\n const buf = await streamToBuffer(ctx.body);\n const contentEncoding = ctx.response.headers['content-encoding'];\n const decompressed = await decompressBuffer(buf, contentEncoding);\n const responseText = decodeBufferToText(decompressed);\n\n const headersToStore = cacheHeaders ? ctx.response.headers : null;\n await cacheStore.set(key, { body: responseText, headers: headersToStore });\n ctx.body = buf;\n } else {\n const headersToStore = cacheHeaders ? ctx.response.headers : null;\n await cacheStore.set(key, { body: ctx.body, headers: headersToStore });\n }\n }\n};\n\nexport default middleware;\n","import rawBody from 'raw-body';\nimport { generateGraphqlCacheKey } from '../utils/key';\nimport Stream, { Readable } from 'stream';\nimport { loggy } from '../utils/log';\nimport { CacheService } from '../../src/types/cache.types';\nimport { decodeBufferToText, decompressBuffer, streamToBuffer } from '../../src/utils/body';\n\nconst middleware = async (ctx: any, next: any) => {\n const cacheService = strapi.plugin('strapi-cache').services.service as CacheService;\n const cacheHeaders = strapi.plugin('strapi-cache').config('cacheHeaders') as boolean;\n const cacheAuthorizedRequests = strapi\n .plugin('strapi-cache')\n .config('cacheAuthorizedRequests') as boolean;\n const cacheStore = cacheService.getCacheInstance();\n const { url } = ctx.request;\n\n const originalReq = ctx.req;\n const bodyBuffer = await rawBody(originalReq);\n const body = bodyBuffer.toString();\n\n const clonedReq = new Readable();\n clonedReq.push(bodyBuffer);\n clonedReq.push(null);\n\n (clonedReq as any).headers = { ...originalReq.headers };\n (clonedReq as any).method = originalReq.method;\n (clonedReq as any).url = originalReq.url;\n (clonedReq as any).httpVersion = originalReq.httpVersion;\n (clonedReq as any).socket = originalReq.socket;\n (clonedReq as any).connection = originalReq.connection;\n\n ctx.req = clonedReq;\n ctx.request.req = clonedReq;\n\n const isIntrospectionQuery = body.includes('IntrospectionQuery');\n if (isIntrospectionQuery) {\n loggy.info('Skipping cache for introspection query');\n await next();\n return;\n }\n\n const key = generateGraphqlCacheKey(body);\n const cacheEntry = await cacheStore.get(key);\n const cacheControlHeader = ctx.request.headers['cache-control'];\n const noCache = cacheControlHeader && cacheControlHeader.includes('no-cache');\n const authorizationHeader = ctx.request.headers['authorization'];\n\n if (authorizationHeader && !cacheAuthorizedRequests) {\n loggy.info(`Authorized request bypassing cache: ${key}`);\n await next();\n return;\n }\n\n if (cacheEntry && !noCache) {\n loggy.info(`HIT with key: ${key}`);\n ctx.status = 200;\n ctx.body = cacheEntry.body;\n if (cacheHeaders) {\n ctx.set(cacheEntry.headers);\n }\n return;\n }\n\n await next();\n\n if (\n ctx.method === 'POST' &&\n ctx.status >= 200 &&\n ctx.status < 300 &&\n url.startsWith('/graphql')\n ) {\n loggy.info(`MISS with key: ${key}`);\n const headers = ctx.request.headers;\n const authorizationHeader = headers['authorization'];\n if (authorizationHeader && !cacheAuthorizedRequests) {\n loggy.info(`Authorized request not caching: ${key}`);\n return;\n }\n\n if (ctx.body instanceof Stream) {\n const buf = await streamToBuffer(ctx.body);\n const contentEncoding = ctx.response.headers['content-encoding']; // e.g., gzip, br, deflate\n const decompressed = await decompressBuffer(buf, contentEncoding);\n const responseText = decodeBufferToText(decompressed);\n\n const headersToStore = cacheHeaders ? ctx.response.headers : null;\n await cacheStore.set(key, { body: responseText, headers: headersToStore });\n ctx.body = buf;\n } else {\n const headersToStore = cacheHeaders ? ctx.response.headers : null;\n await cacheStore.set(key, {\n body: ctx.body,\n headers: headersToStore,\n });\n }\n }\n};\n\nexport default middleware;\n","import cache from './cache';\nimport graphql from './graphql';\n\nexport default {\n graphql,\n cache,\n};\n","import type { Core } from '@strapi/strapi';\nimport middlewares from './middlewares';\n\nconst register = ({ strapi }: { strapi: Core.Strapi }) => {\n strapi.server.use(middlewares.cache);\n strapi.server.use(middlewares.graphql);\n};\n\nexport default register;\n","export default {\n default: ({ env }) => ({\n debug: false,\n max: 1000,\n ttl: 1000 * 60 * 60,\n size: 1024 * 1014 * 10,\n allowStale: false,\n cacheableRoutes: [],\n provider: 'memory',\n redisConfig: env('REDIS_URL'),\n cacheHeaders: true,\n cacheAuthorizedRequests: false,\n cacheGetTimeoutInMs: 1000,\n }),\n validator: (config) => {\n if (typeof config.debug !== 'boolean') {\n throw new Error(`Invalid config: debug must be a boolean`);\n }\n if (typeof config.max !== 'number') {\n throw new Error(`Invalid config: max must be a number`);\n }\n if (typeof config.ttl !== 'number') {\n throw new Error(`Invalid config: ttl must be a number`);\n }\n if (typeof config.size !== 'number') {\n throw new Error(`Invalid config: size must be a number`);\n }\n if (typeof config.allowStale !== 'boolean') {\n throw new Error(`Invalid config: allowStale must be a boolean`);\n }\n if (\n !Array.isArray(config.cacheableRoutes) ||\n config.cacheableRoutes.some((item) => typeof item !== 'string')\n ) {\n throw new Error(`Invalid config: cacheableRoutes must be an string array`);\n }\n if (typeof config.provider !== 'string') {\n throw new Error(`Invalid config: provider must be a string`);\n }\n if (config.provider !== 'memory' && config.provider !== 'redis') {\n throw new Error(`Invalid config: provider must be 'memory' or 'redis'`);\n }\n if (\n config.provider === 'redis' &&\n !config.redisConfig &&\n (typeof config.redisConfig !== 'string' || typeof config.redisConfig !== 'object')\n ) {\n throw new Error(`Invalid config: redisConfig must be set when using redis provider`);\n }\n if (typeof config.cacheHeaders !== 'boolean') {\n throw new Error(`Invalid config: cacheHeaders must be a boolean`);\n }\n if (typeof config.cacheAuthorizedRequests !== 'boolean') {\n throw new Error(`Invalid config: cacheAuthorizedRequests must be a boolean`);\n }\n\n if (typeof config.cacheGetTimeoutInMs !== 'number') {\n throw new Error(`Invalid config: cacheGetTimeoutInMs must be a number`);\n }\n },\n};\n","export default {};\n","import type { Core } from '@strapi/strapi';\nimport { Context } from 'koa';\nimport { CacheService } from 'src/types/cache.types';\n\nconst controller = ({ strapi }: { strapi: Core.Strapi }) => ({\n async purgeCache(ctx: Context) {\n const service = strapi.plugin('strapi-cache').service('service') as CacheService;\n\n await service.getCacheInstance().reset();\n\n ctx.body = {\n message: 'Cache purged successfully',\n };\n },\n async purgeCacheByKey(ctx: Context) {\n const { key } = ctx.params;\n const service = strapi.plugin('strapi-cache').service('service') as CacheService;\n const regex = new RegExp(`(^|\\/)${key}(\\/|\\\\?|$)`);\n\n await service.getCacheInstance().clearByRegexp([regex]);\n\n ctx.body = {\n message: `Cache purged successfully for key: ${key}`,\n };\n },\n async cacheableRoutes(ctx: Context) {\n const cacheableRoutes = strapi.plugin('strapi-cache').config('cacheableRoutes');\n ctx.body = cacheableRoutes;\n },\n});\n\nexport default controller;\n","import controller from './controller';\n\nexport default {\n controller,\n};\n","export default {};\n","export default [\n {\n method: 'POST',\n path: '/purge-cache',\n handler: 'controller.purgeCache',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'plugin::content-manager.hasPermissions',\n config: {\n actions: ['plugin::strapi-cache.purge-cache'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/purge-cache/:key',\n handler: 'controller.purgeCacheByKey',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'plugin::content-manager.hasPermissions',\n config: {\n actions: ['plugin::strapi-cache.purge-cache'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/cacheable-routes',\n handler: 'controller.cacheableRoutes',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'plugin::content-manager.hasPermissions',\n config: {\n actions: ['plugin::strapi-cache.purge-cache'],\n },\n },\n ],\n },\n },\n];\n","import purgeRoute from './purge';\n\nconst routes = {\n 'purge-route': {\n type: 'admin',\n routes: purgeRoute,\n },\n};\n\nexport default routes;\n","export const withTimeout = (callback: () => Promise<any>, ms: number) => {\n let timeout: NodeJS.Timeout | null = null;\n\n return Promise.race([\n callback().then((result) => {\n if (timeout) {\n clearTimeout(timeout);\n }\n return result;\n }),\n new Promise((_, reject) => {\n timeout = setTimeout(() => {\n reject(new Error('timeout'));\n }, ms);\n }),\n ]);\n};\n","import type { Core } from '@strapi/strapi';\nimport { LRUCache } from 'lru-cache';\nimport { withTimeout } from '../../utils/withTimeout';\nimport { CacheProvider, CacheService } from '../../types/cache.types';\nimport { loggy } from '../../utils/log';\n\nexport class InMemoryCacheProvider implements CacheProvider {\n private initialized = false;\n private provider!: LRUCache<string, any>;\n private cacheGetTimeoutInMs: number;\n\n constructor(private strapi: Core.Strapi) {}\n\n init(): void {\n if (this.initialized) {\n loggy.error('Provider already initialized');\n return;\n }\n\n this.initialized = true;\n\n const max = Number(this.strapi.plugin('strapi-cache').config('max'));\n const ttl = Number(this.strapi.plugin('strapi-cache').config('ttl'));\n const size = Number(this.strapi.plugin('strapi-cache').config('size'));\n const allowStale = Boolean(this.strapi.plugin('strapi-cache').config('allowStale'));\n\n this.provider = new LRUCache({\n max,\n ttl,\n size,\n allowStale,\n });\n\n this.cacheGetTimeoutInMs = Number(\n this.strapi.plugin('strapi-cache').config('cacheGetTimeoutInMs')\n );\n\n loggy.info('Provider initialized');\n }\n\n get ready(): boolean {\n if (!this.initialized) {\n loggy.info('Provider not initialized');\n return false;\n }\n\n return true;\n }\n\n async get(key: string): Promise<any | null> {\n if (!this.ready) return null;\n\n return withTimeout(\n () =>\n new Promise((resolve) => {\n resolve(this.provider.get(key));\n }),\n this.cacheGetTimeoutInMs\n ).catch((error) => {\n loggy.error(`Error during get: ${error?.message || error}`);\n return null;\n });\n }\n\n async set(key: string, val: any): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n return this.provider.set(key, val);\n } catch (error) {\n loggy.error(`Error during set: ${error}`);\n return null;\n }\n }\n\n async del(key: string): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n loggy.info(`PURGING KEY: ${key}`);\n return this.provider.delete(key);\n } catch (error) {\n loggy.error(`Error during delete: ${error}`);\n return null;\n }\n }\n\n async keys(): Promise<string[] | null> {\n if (!this.ready) return null;\n\n try {\n return Array.from(this.provider.keys());\n } catch (error) {\n loggy.error(`Error fetching keys: ${error}`);\n return null;\n }\n }\n\n async reset(): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n const allKeys = await this.keys();\n if (!allKeys) return null;\n\n loggy.info(`PURGING ALL KEYS: ${allKeys.length}`);\n await Promise.all(allKeys.map((key) => this.del(key)));\n return true;\n } catch (error) {\n loggy.error(`Error during reset: ${error}`);\n return null;\n }\n }\n\n async clearByRegexp(regExps: RegExp[]): Promise<void> {\n const keys = (await this.keys()) || [];\n const matches = keys.filter((key) => regExps.some((re) => re.test(key)));\n await Promise.all(matches.map((key) => this.del(key)));\n }\n}\n","import type { Core } from '@strapi/strapi';\nimport Redis from 'ioredis';\nimport { withTimeout } from '../../utils/withTimeout';\nimport { CacheProvider } from '../../types/cache.types';\nimport { loggy } from '../../utils/log';\n\nexport class RedisCacheProvider implements CacheProvider {\n private initialized = false;\n private client!: Redis;\n private cacheGetTimeoutInMs: number;\n\n constructor(private strapi: Core.Strapi) {}\n\n init(): void {\n if (this.initialized) {\n loggy.error('Redis provider already initialized');\n return;\n }\n try {\n const redisUrl =\n this.strapi.plugin('strapi-cache').config('redisConfig') || 'redis://localhost:6379';\n this.cacheGetTimeoutInMs = Number(\n this.strapi.plugin('strapi-cache').config('cacheGetTimeoutInMs')\n );\n this.client = new Redis(redisUrl);\n this.initialized = true;\n\n loggy.info('Redis provider initialized');\n } catch (error) {\n loggy.error(error);\n }\n }\n\n get ready(): boolean {\n if (!this.initialized) {\n loggy.info('Redis provider not initialized');\n return false;\n }\n\n return true;\n }\n\n async get(key: string): Promise<any | null> {\n if (!this.ready) return null;\n\n return withTimeout(() => this.client.get(key), this.cacheGetTimeoutInMs)\n .then((data) => (data ? JSON.parse(data) : null))\n .catch((error) => {\n loggy.error(`Redis get error: ${error?.message || error}`);\n return null;\n });\n }\n\n async set(key: string, val: any): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n const ttl = Number(this.strapi.plugin('strapi-cache').config('ttl'));\n const serialized = JSON.stringify(val);\n if (ttl > 0) {\n await this.client.set(key, serialized, 'EX', ttl);\n } else {\n await this.client.set(key, serialized);\n }\n return val;\n } catch (error) {\n loggy.error(`Redis set error: ${error}`);\n return null;\n }\n }\n\n async del(key: string): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n loggy.info(`Redis PURGING KEY: ${key}`);\n await this.client.del(key);\n return true;\n } catch (error) {\n loggy.error(`Redis del error: ${error}`);\n return null;\n }\n }\n\n async keys(): Promise<string[] | null> {\n if (!this.ready) return null;\n\n try {\n const keys = await this.client.keys('*');\n return keys;\n } catch (error) {\n loggy.error(`Redis keys error: ${error}`);\n return null;\n }\n }\n\n async reset(): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n loggy.info(`Redis FLUSHING ALL KEYS`);\n await this.client.flushdb();\n return true;\n } catch (error) {\n loggy.error(`Redis reset error: ${error}`);\n return null;\n }\n }\n\n async clearByRegexp(regExps: RegExp[]): Promise<void> {\n const keys = await this.keys();\n if (!keys) return;\n\n const toDelete = keys.filter((key) => regExps.some((re) => re.test(key)));\n await Promise.all(toDelete.map((key) => this.del(key)));\n }\n}\n","import type { Core } from '@strapi/strapi';\nimport { InMemoryCacheProvider } from './memory/provider';\nimport { RedisCacheProvider } from './redis/provider';\nimport { CacheProvider } from '../../src/types/cache.types';\nimport { loggy } from '../../src/utils/log';\n\nexport const resolveCacheProvider = (strapi: Core.Strapi): CacheProvider => {\n const providerType = strapi.plugin('strapi-cache').config('provider') || 'memory';\n\n loggy.info(`Selected cache provider: ${providerType}`);\n\n let instance: CacheProvider;\n\n switch (providerType) {\n case 'redis':\n instance = new RedisCacheProvider(strapi);\n break;\n default:\n instance = new InMemoryCacheProvider(strapi);\n break;\n }\n\n return instance;\n};\n","import type { Core } from '@strapi/strapi';\nimport { resolveCacheProvider } from './resolver';\nimport { CacheProvider, CacheService } from '../../src/types/cache.types';\nimport { loggy } from '../../src/utils/log';\n\nconst service = ({ strapi }: { strapi: Core.Strapi }): CacheService => {\n let instance: null | CacheProvider = null;\n\n return {\n getCacheInstance() {\n if (!instance) {\n loggy.info('Initializing cache service from provider config...');\n instance = resolveCacheProvider(strapi);\n }\n return instance;\n },\n };\n};\n\nexport default {\n service,\n};\n","/**\n * Application methods\n */\nimport bootstrap from './bootstrap';\nimport register from './register';\n\n/**\n * Plugin server methods\n */\nimport config from './config';\nimport contentTypes from './content-types';\nimport controllers from './controllers';\nimport middlewares from './middlewares';\nimport policies from './policies';\nimport routes from './routes';\nimport services from './services';\n\nexport default {\n register,\n bootstrap,\n destroy() {},\n config,\n controllers,\n routes,\n services,\n contentTypes,\n policies,\n middlewares,\n};\n"],"names":["strapi","createHash","createGunzip","createBrotliDecompress","createInflate","middleware","Stream","rawBody","Readable","authorizationHeader","graphql","cache","config","service","LRUCache","Redis"],"mappings":";;;;;;;;;;;AAAO,MAAM,QAAQ;AAAA,EACnB,MAAM,CAAC,QAAgB;AACrB,UAAM,cAAc,OAAO,OAAO,cAAc,EAAE,OAAO,OAAO,KAAK;AACrE,QAAI,CAAC,aAAa;AAChB;AAAA,IAAA;AAEF,WAAO,IAAI,KAAK,kBAAkB,GAAG,EAAE;AAAA,EACzC;AAAA,EACA,OAAO,CAAC,QAAgB;AACtB,UAAM,cAAc,OAAO,OAAO,cAAc,EAAE,OAAO,OAAO,KAAK;AACrE,QAAI,CAAC,aAAa;AAChB;AAAA,IAAA;AAEF,WAAO,IAAI,MAAM,kBAAkB,GAAG,EAAE;AAAA,EAC1C;AAAA,EACA,MAAM,CAAC,QAAgB;AACrB,UAAM,cAAc,OAAO,OAAO,cAAc,EAAE,OAAO,OAAO,KAAK;AACrE,QAAI,CAAC,aAAa;AAChB;AAAA,IAAA;AAEF,WAAO,IAAI,KAAK,kBAAkB,GAAG,EAAE;AAAA,EAAA;AAE3C;AClBsB,eAAA,gBAAgB,OAAY,YAA2BA,SAAqB;AAC1F,QAAA,EAAE,UAAU;AAClB,QAAM,MAAM,MAAM;AAEd,MAAA;AACI,UAAA,cAAcA,QAAO,YAAY,GAAG;AAE1C,QAAI,CAAC,eAAe,CAAC,YAAY,MAAM;AAC/B,YAAA,KAAK,gBAAgB,GAAG,YAAY;AAC1C;AAAA,IAAA;AAGI,UAAA,aACJ,YAAY,SAAS,eACjB,YAAY,KAAK,eACjB,YAAY,KAAK;AACjB,UAAA,UAAU,QAAQ,UAAU;AAClC,UAAM,QAAQ,IAAI,OAAO,OAAO,OAAO,iBAAiB;AAExD,UAAM,WAAW,cAAc,CAAC,KAAK,CAAC;AAChC,UAAA,KAAK,yBAAyB,OAAO,EAAE;AAAA,WACtC,OAAO;AACd,UAAM,MAAM,2BAA2B;AACvC,UAAM,MAAM,KAAK;AAAA,EAAA;AAErB;AAEsB,eAAA,uBACpB,OACA,YACAA,SACA;AACI,MAAA;AACI,UAAA,eAAe,IAAI,OAAO,uBAAwB;AAExD,UAAM,WAAW,cAAc,CAAC,YAAY,CAAC;AACvC,UAAA,KAAK,yBAAyB,YAAY,EAAE;AAAA,WAC3C,OAAO;AACd,UAAM,MAAM,2BAA2B;AACvC,UAAM,MAAM,KAAK;AAAA,EAAA;AAErB;AC7CO,MAAM,UAAU;AAAA,EACrB;AAAA,IACE,SAAS;AAAA,IACT,aAAa;AAAA,IACb,KAAK;AAAA,IACL,YAAY;AAAA,EAAA;AAEhB;ACDA,MAAM,YAAY,CAAC,EAAE,QAAAA,cAAsC;AACzD,QAAM,KAAK,cAAc;AACrB,MAAA;AACF,UAAM,eAAeA,QAAO,OAAO,cAAc,EAAE,SAAS;AACtD,UAAA,aAAa,aAAa,iBAAiB;AACjD,eAAW,KAAK;AAET,IAAAA,QAAA,GAAG,WAAW,UAAU;AAAA,MAC7B,MAAM,YAAY,OAAO;AACjB,cAAA,gBAAgB,OAAO,YAAYA,OAAM;AACzC,cAAA,uBAAuB,OAAO,YAAYA,OAAM;AAAA,MACxD;AAAA,MACA,MAAM,YAAY,OAAO;AACjB,cAAA,gBAAgB,OAAO,YAAYA,OAAM;AACzC,cAAA,uBAAuB,OAAO,YAAYA,OAAM;AAAA,MACxD;AAAA,MACA,MAAM,YAAY,OAAO;AACjB,cAAA,gBAAgB,OAAO,YAAYA,OAAM;AACzC,cAAA,uBAAuB,OAAO,YAAYA,OAAM;AAAA,MAAA;AAAA,IACxD,CACD;AAED,QAAI,CAAC,YAAY;AACf,YAAM,MAAM,iCAAiC;AAC7C;AAAA,IAAA;AAAA,WAEK,OAAO;AACd,UAAM,MAAM,iCAAiC;AAC7C;AAAA,EAAA;AAEF,QAAM,KAAK,oBAAoB;AAE/B,EAAAA,QAAO,MAAM,SAAS,WAAW,eAAe,aAAa,OAAO;AACtE;ACpCa,MAAA,mBAAmB,CAAC,YAAqB;AAC9C,QAAA,EAAE,QAAQ,QAAQ;AAClB,QAAA,EAAE,WAAW,QAAQ;AAEpB,SAAA,GAAG,MAAM,IAAI,GAAG;AACzB;AAEa,MAAA,0BAA0B,CAAC,YAAoB;AACpD,QAAA,OAAOC,kBAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,WAAW;AACpE,SAAO,iBAAiB,IAAI;AAC9B;ACVa,MAAA,iBAAiB,CAAC,WAAoC;AACjE,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAmB,CAAC;AAC1B,WAAO,GAAG,QAAQ,CAAC,UAAU,OAAO,KAAK,KAAK,CAAC;AACxC,WAAA,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC;AAC9C,WAAA,GAAG,SAAS,MAAM;AAAA,EAAA,CAC1B;AACH;AAEa,MAAA,mBAAmB,OAAO,QAAgB,aAAuC;AAC5F,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AAClC,QAAA;AACJ,YAAQ,UAAU;AAAA,MAChB,KAAK;AACH,2BAAmBC,KAAAA,aAAa;AAChC;AAAA,MACF,KAAK;AACH,2BAAmBC,KAAAA,uBAAuB;AAC1C;AAAA,MACF,KAAK;AACH,2BAAmBC,KAAAA,cAAc;AACjC;AAAA,MACF;AACE,eAAO,QAAQ,MAAM;AAAA,IAAA;AAGzB,UAAM,SAAmB,CAAC;AAC1B,qBAAiB,GAAG,QAAQ,CAAC,UAAU,OAAO,KAAK,KAAK,CAAC;AACxC,qBAAA,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC,CAAC;AAC9C,qBAAA,GAAG,SAAS,MAAM;AAEnC,qBAAiB,IAAI,MAAM;AAAA,EAAA,CAC5B;AACH;AAEa,MAAA,qBAAqB,CAAC,WAA2B;AACtD,QAAA,UAAU,IAAI,YAAY,OAAO;AAChC,SAAA,QAAQ,OAAO,MAAM;AAC9B;AClCA,MAAMC,eAAa,OAAO,KAAc,SAAc;AACpD,QAAM,eAAe,OAAO,OAAO,cAAc,EAAE,SAAS;AAC5D,QAAM,kBAAkB,OAAO,OAAO,cAAc,EAAE,OAAO,iBAAiB;AAC9E,QAAM,eAAe,OAAO,OAAO,cAAc,EAAE,OAAO,cAAc;AACxE,QAAM,0BAA0B,OAC7B,OAAO,cAAc,EACrB,OAAO,yBAAyB;AAC7B,QAAA,aAAa,aAAa,iBAAiB;AAC3C,QAAA,EAAE,QAAQ,IAAI;AACd,QAAA,MAAM,iBAAiB,GAAG;AAChC,QAAM,aAAa,MAAM,WAAW,IAAI,GAAG;AAC3C,QAAM,qBAAqB,IAAI,QAAQ,QAAQ,eAAe;AAC9D,QAAM,UAAU,sBAAsB,mBAAmB,SAAS,UAAU;AAC5E,QAAM,kBACJ,gBAAgB,KAAK,CAAC,UAAU,IAAI,WAAW,KAAK,CAAC,KACpD,gBAAgB,WAAW,KAAK,IAAI,WAAW,MAAM;AACxD,QAAM,sBAAsB,IAAI,QAAQ,QAAQ,eAAe;AAE3D,MAAA,uBAAuB,CAAC,yBAAyB;AAC7C,UAAA,KAAK,uCAAuC,GAAG,EAAE;AACvD,UAAM,KAAK;AACX;AAAA,EAAA;AAGE,MAAA,cAAc,CAAC,SAAS;AACpB,UAAA,KAAK,iBAAiB,GAAG,EAAE;AACjC,QAAI,SAAS;AACb,QAAI,OAAO,WAAW;AACtB,QAAI,cAAc;AACZ,UAAA,IAAI,WAAW,OAAO;AAAA,IAAA;AAE5B;AAAA,EAAA;AAGF,QAAM,KAAK;AAEP,MAAA,IAAI,WAAW,SAAS,IAAI,UAAU,OAAO,IAAI,SAAS,OAAO,iBAAiB;AAC9E,UAAA,KAAK,kBAAkB,GAAG,EAAE;AAE9B,QAAA,IAAI,gBAAgBC,yBAAQ;AAC9B,YAAM,MAAM,MAAM,eAAe,IAAI,IAAI;AACzC,YAAM,kBAAkB,IAAI,SAAS,QAAQ,kBAAkB;AAC/D,YAAM,eAAe,MAAM,iBAAiB,KAAK,eAAe;AAC1D,YAAA,eAAe,mBAAmB,YAAY;AAEpD,YAAM,iBAAiB,eAAe,IAAI,SAAS,UAAU;AACvD,YAAA,WAAW,IAAI,KAAK,EAAE,MAAM,cAAc,SAAS,gBAAgB;AACzE,UAAI,OAAO;AAAA,IAAA,OACN;AACL,YAAM,iBAAiB,eAAe,IAAI,SAAS,UAAU;AACvD,YAAA,WAAW,IAAI,KAAK,EAAE,MAAM,IAAI,MAAM,SAAS,gBAAgB;AAAA,IAAA;AAAA,EACvE;AAEJ;ACrDA,MAAM,aAAa,OAAO,KAAU,SAAc;AAChD,QAAM,eAAe,OAAO,OAAO,cAAc,EAAE,SAAS;AAC5D,QAAM,eAAe,OAAO,OAAO,cAAc,EAAE,OAAO,cAAc;AACxE,QAAM,0BAA0B,OAC7B,OAAO,cAAc,EACrB,OAAO,yBAAyB;AAC7B,QAAA,aAAa,aAAa,iBAAiB;AAC3C,QAAA,EAAE,QAAQ,IAAI;AAEpB,QAAM,cAAc,IAAI;AAClB,QAAA,aAAa,MAAMC,iBAAA,QAAQ,WAAW;AACtC,QAAA,OAAO,WAAW,SAAS;AAE3B,QAAA,YAAY,IAAIC,gBAAS;AAC/B,YAAU,KAAK,UAAU;AACzB,YAAU,KAAK,IAAI;AAElB,YAAkB,UAAU,EAAE,GAAG,YAAY,QAAQ;AACrD,YAAkB,SAAS,YAAY;AACvC,YAAkB,MAAM,YAAY;AACpC,YAAkB,cAAc,YAAY;AAC5C,YAAkB,SAAS,YAAY;AACvC,YAAkB,aAAa,YAAY;AAE5C,MAAI,MAAM;AACV,MAAI,QAAQ,MAAM;AAEZ,QAAA,uBAAuB,KAAK,SAAS,oBAAoB;AAC/D,MAAI,sBAAsB;AACxB,UAAM,KAAK,wCAAwC;AACnD,UAAM,KAAK;AACX;AAAA,EAAA;AAGI,QAAA,MAAM,wBAAwB,IAAI;AACxC,QAAM,aAAa,MAAM,WAAW,IAAI,GAAG;AAC3C,QAAM,qBAAqB,IAAI,QAAQ,QAAQ,eAAe;AAC9D,QAAM,UAAU,sBAAsB,mBAAmB,SAAS,UAAU;AAC5E,QAAM,sBAAsB,IAAI,QAAQ,QAAQ,eAAe;AAE3D,MAAA,uBAAuB,CAAC,yBAAyB;AAC7C,UAAA,KAAK,uCAAuC,GAAG,EAAE;AACvD,UAAM,KAAK;AACX;AAAA,EAAA;AAGE,MAAA,cAAc,CAAC,SAAS;AACpB,UAAA,KAAK,iBAAiB,GAAG,EAAE;AACjC,QAAI,SAAS;AACb,QAAI,OAAO,WAAW;AACtB,QAAI,cAAc;AACZ,UAAA,IAAI,WAAW,OAAO;AAAA,IAAA;AAE5B;AAAA,EAAA;AAGF,QAAM,KAAK;AAEX,MACE,IAAI,WAAW,UACf,IAAI,UAAU,OACd,IAAI,SAAS,OACb,IAAI,WAAW,UAAU,GACzB;AACM,UAAA,KAAK,kBAAkB,GAAG,EAAE;AAC5B,UAAA,UAAU,IAAI,QAAQ;AACtBC,UAAAA,uBAAsB,QAAQ,eAAe;AAC/CA,QAAAA,wBAAuB,CAAC,yBAAyB;AAC7C,YAAA,KAAK,mCAAmC,GAAG,EAAE;AACnD;AAAA,IAAA;AAGE,QAAA,IAAI,gBAAgBH,yBAAQ;AAC9B,YAAM,MAAM,MAAM,eAAe,IAAI,IAAI;AACzC,YAAM,kBAAkB,IAAI,SAAS,QAAQ,kBAAkB;AAC/D,YAAM,eAAe,MAAM,iBAAiB,KAAK,eAAe;AAC1D,YAAA,eAAe,mBAAmB,YAAY;AAEpD,YAAM,iBAAiB,eAAe,IAAI,SAAS,UAAU;AACvD,YAAA,WAAW,IAAI,KAAK,EAAE,MAAM,cAAc,SAAS,gBAAgB;AACzE,UAAI,OAAO;AAAA,IAAA,OACN;AACL,YAAM,iBAAiB,eAAe,IAAI,SAAS,UAAU;AACvD,YAAA,WAAW,IAAI,KAAK;AAAA,QACxB,MAAM,IAAI;AAAA,QACV,SAAS;AAAA,MAAA,CACV;AAAA,IAAA;AAAA,EACH;AAEJ;AC7FA,MAAe,cAAA;AAAA,EAAA,SACbI;AAAAA,EACAC,OAAAA;AACF;ACHA,MAAM,WAAW,CAAC,EAAE,QAAAX,cAAsC;AACjD,EAAAA,QAAA,OAAO,IAAI,YAAY,KAAK;AAC5B,EAAAA,QAAA,OAAO,IAAI,YAAY,OAAO;AACvC;ACNA,MAAe,SAAA;AAAA,EACb,SAAS,CAAC,EAAE,WAAW;AAAA,IACrB,OAAO;AAAA,IACP,KAAK;AAAA,IACL,KAAK,MAAO,KAAK;AAAA,IACjB,MAAM,OAAO,OAAO;AAAA,IACpB,YAAY;AAAA,IACZ,iBAAiB,CAAC;AAAA,IAClB,UAAU;AAAA,IACV,aAAa,IAAI,WAAW;AAAA,IAC5B,cAAc;AAAA,IACd,yBAAyB;AAAA,IACzB,qBAAqB;AAAA,EAAA;AAAA,EAEvB,WAAW,CAACY,YAAW;AACjB,QAAA,OAAOA,QAAO,UAAU,WAAW;AAC/B,YAAA,IAAI,MAAM,yCAAyC;AAAA,IAAA;AAEvD,QAAA,OAAOA,QAAO,QAAQ,UAAU;AAC5B,YAAA,IAAI,MAAM,sCAAsC;AAAA,IAAA;AAEpD,QAAA,OAAOA,QAAO,QAAQ,UAAU;AAC5B,YAAA,IAAI,MAAM,sCAAsC;AAAA,IAAA;AAEpD,QAAA,OAAOA,QAAO,SAAS,UAAU;AAC7B,YAAA,IAAI,MAAM,uCAAuC;AAAA,IAAA;AAErD,QAAA,OAAOA,QAAO,eAAe,WAAW;AACpC,YAAA,IAAI,MAAM,8CAA8C;AAAA,IAAA;AAEhE,QACE,CAAC,MAAM,QAAQA,QAAO,eAAe,KACrCA,QAAO,gBAAgB,KAAK,CAAC,SAAS,OAAO,SAAS,QAAQ,GAC9D;AACM,YAAA,IAAI,MAAM,yDAAyD;AAAA,IAAA;AAEvE,QAAA,OAAOA,QAAO,aAAa,UAAU;AACjC,YAAA,IAAI,MAAM,2CAA2C;AAAA,IAAA;AAE7D,QAAIA,QAAO,aAAa,YAAYA,QAAO,aAAa,SAAS;AACzD,YAAA,IAAI,MAAM,sDAAsD;AAAA,IAAA;AAExE,QACEA,QAAO,aAAa,WACpB,CAACA,QAAO,gBACP,OAAOA,QAAO,gBAAgB,YAAY,OAAOA,QAAO,gBAAgB,WACzE;AACM,YAAA,IAAI,MAAM,mEAAmE;AAAA,IAAA;AAEjF,QAAA,OAAOA,QAAO,iBAAiB,WAAW;AACtC,YAAA,IAAI,MAAM,gDAAgD;AAAA,IAAA;AAE9D,QAAA,OAAOA,QAAO,4BAA4B,WAAW;AACjD,YAAA,IAAI,MAAM,2DAA2D;AAAA,IAAA;AAGzE,QAAA,OAAOA,QAAO,wBAAwB,UAAU;AAC5C,YAAA,IAAI,MAAM,sDAAsD;AAAA,IAAA;AAAA,EACxE;AAEJ;AC5DA,MAAA,eAAe,CAAC;ACIhB,MAAM,aAAa,CAAC,EAAE,QAAAZ,eAAuC;AAAA,EAC3D,MAAM,WAAW,KAAc;AAC7B,UAAMa,WAAUb,QAAO,OAAO,cAAc,EAAE,QAAQ,SAAS;AAEzD,UAAAa,SAAQ,iBAAiB,EAAE,MAAM;AAEvC,QAAI,OAAO;AAAA,MACT,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,MAAM,gBAAgB,KAAc;AAC5B,UAAA,EAAE,QAAQ,IAAI;AACpB,UAAMA,WAAUb,QAAO,OAAO,cAAc,EAAE,QAAQ,SAAS;AAC/D,UAAM,QAAQ,IAAI,OAAO,QAAS,GAAG,WAAY;AAEjD,UAAMa,SAAQ,iBAAiB,EAAE,cAAc,CAAC,KAAK,CAAC;AAEtD,QAAI,OAAO;AAAA,MACT,SAAS,sCAAsC,GAAG;AAAA,IACpD;AAAA,EACF;AAAA,EACA,MAAM,gBAAgB,KAAc;AAClC,UAAM,kBAAkBb,QAAO,OAAO,cAAc,EAAE,OAAO,iBAAiB;AAC9E,QAAI,OAAO;AAAA,EAAA;AAEf;AC3BA,MAAe,cAAA;AAAA,EACb;AACF;ACJA,MAAA,WAAe,CAAC;ACAhB,MAAe,aAAA;AAAA,EACb;AAAA,IACE,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,MACN,UAAU;AAAA,QACR;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,SAAS,CAAC,kCAAkC;AAAA,UAAA;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,EAEJ;AAAA,EACA;AAAA,IACE,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,MACN,UAAU;AAAA,QACR;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,SAAS,CAAC,kCAAkC;AAAA,UAAA;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,EAEJ;AAAA,EACA;AAAA,IACE,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,MACN,UAAU;AAAA,QACR;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,SAAS,CAAC,kCAAkC;AAAA,UAAA;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEJ;AC/CA,MAAM,SAAS;AAAA,EACb,eAAe;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAEZ;ACPa,MAAA,cAAc,CAAC,UAA8B,OAAe;AACvE,MAAI,UAAiC;AAErC,SAAO,QAAQ,KAAK;AAAA,IAClB,SAAS,EAAE,KAAK,CAAC,WAAW;AAC1B,UAAI,SAAS;AACX,qBAAa,OAAO;AAAA,MAAA;AAEf,aAAA;AAAA,IAAA,CACR;AAAA,IACD,IAAI,QAAQ,CAAC,GAAG,WAAW;AACzB,gBAAU,WAAW,MAAM;AAClB,eAAA,IAAI,MAAM,SAAS,CAAC;AAAA,SAC1B,EAAE;AAAA,IACN,CAAA;AAAA,EAAA,CACF;AACH;ACVO,MAAM,sBAA+C;AAAA,EAK1D,YAAoBA,SAAqB;AAArB,SAAA,SAAAA;AAJpB,SAAQ,cAAc;AAAA,EAAA;AAAA,EAMtB,OAAa;AACX,QAAI,KAAK,aAAa;AACpB,YAAM,MAAM,8BAA8B;AAC1C;AAAA,IAAA;AAGF,SAAK,cAAc;AAEb,UAAA,MAAM,OAAO,KAAK,OAAO,OAAO,cAAc,EAAE,OAAO,KAAK,CAAC;AAC7D,UAAA,MAAM,OAAO,KAAK,OAAO,OAAO,cAAc,EAAE,OAAO,KAAK,CAAC;AAC7D,UAAA,OAAO,OAAO,KAAK,OAAO,OAAO,cAAc,EAAE,OAAO,MAAM,CAAC;AAC/D,UAAA,aAAa,QAAQ,KAAK,OAAO,OAAO,cAAc,EAAE,OAAO,YAAY,CAAC;AAE7E,SAAA,WAAW,IAAIc,kBAAS;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACD;AAED,SAAK,sBAAsB;AAAA,MACzB,KAAK,OAAO,OAAO,cAAc,EAAE,OAAO,qBAAqB;AAAA,IACjE;AAEA,UAAM,KAAK,sBAAsB;AAAA,EAAA;AAAA,EAGnC,IAAI,QAAiB;AACf,QAAA,CAAC,KAAK,aAAa;AACrB,YAAM,KAAK,0BAA0B;AAC9B,aAAA;AAAA,IAAA;AAGF,WAAA;AAAA,EAAA;AAAA,EAGT,MAAM,IAAI,KAAkC;AACtC,QAAA,CAAC,KAAK,MAAc,QAAA;AAEjB,WAAA;AAAA,MACL,MACE,IAAI,QAAQ,CAAC,YAAY;AACvB,gBAAQ,KAAK,SAAS,IAAI,GAAG,CAAC;AAAA,MAAA,CAC/B;AAAA,MACH,KAAK;AAAA,IAAA,EACL,MAAM,CAAC,UAAU;AACjB,YAAM,MAAM,qBAAqB,OAAO,WAAW,KAAK,EAAE;AACnD,aAAA;AAAA,IAAA,CACR;AAAA,EAAA;AAAA,EAGH,MAAM,IAAI,KAAa,KAA+B;AAChD,QAAA,CAAC,KAAK,MAAc,QAAA;AAEpB,QAAA;AACF,aAAO,KAAK,SAAS,IAAI,KAAK,GAAG;AAAA,aAC1B,OAAO;AACR,YAAA,MAAM,qBAAqB,KAAK,EAAE;AACjC,aAAA;AAAA,IAAA;AAAA,EACT;AAAA,EAGF,MAAM,IAAI,KAAkC;AACtC,QAAA,CAAC,KAAK,MAAc,QAAA;AAEpB,QAAA;AACI,YAAA,KAAK,gBAAgB,GAAG,EAAE;AACzB,aAAA,KAAK,SAAS,OAAO,GAAG;AAAA,aACxB,OAAO;AACR,YAAA,MAAM,wBAAwB,KAAK,EAAE;AACpC,aAAA;AAAA,IAAA;AAAA,EACT;AAAA,EAGF,MAAM,OAAiC;AACjC,QAAA,CAAC,KAAK,MAAc,QAAA;AAEpB,QAAA;AACF,aAAO,MAAM,KAAK,KAAK,SAAS,MAAM;AAAA,aAC/B,OAAO;AACR,YAAA,MAAM,wBAAwB,KAAK,EAAE;AACpC,aAAA;AAAA,IAAA;AAAA,EACT;AAAA,EAGF,MAAM,QAA6B;AAC7B,QAAA,CAAC,KAAK,MAAc,QAAA;AAEpB,QAAA;AACI,YAAA,UAAU,MAAM,KAAK,KAAK;AAC5B,UAAA,CAAC,QAAgB,QAAA;AAErB,YAAM,KAAK,qBAAqB,QAAQ,MAAM,EAAE;AAC1C,YAAA,QAAQ,IAAI,QAAQ,IAAI,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC,CAAC;AAC9C,aAAA;AAAA,aACA,OAAO;AACR,YAAA,MAAM,uBAAuB,KAAK,EAAE;AACnC,aAAA;AAAA,IAAA;AAAA,EACT;AAAA,EAGF,MAAM,cAAc,SAAkC;AACpD,UAAM,OAAQ,MAAM,KAAK,UAAW,CAAC;AACrC,UAAM,UAAU,KAAK,OAAO,CAAC,QAAQ,QAAQ,KAAK,CAAC,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC;AACjE,UAAA,QAAQ,IAAI,QAAQ,IAAI,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC,CAAC;AAAA,EAAA;AAEzD;ACjHO,MAAM,mBAA4C;AAAA,EAKvD,YAAoBd,SAAqB;AAArB,SAAA,SAAAA;AAJpB,SAAQ,cAAc;AAAA,EAAA;AAAA,EAMtB,OAAa;AACX,QAAI,KAAK,aAAa;AACpB,YAAM,MAAM,oCAAoC;AAChD;AAAA,IAAA;AAEE,QAAA;AACI,YAAA,WACJ,KAAK,OAAO,OAAO,cAAc,EAAE,OAAO,aAAa,KAAK;AAC9D,WAAK,sBAAsB;AAAA,QACzB,KAAK,OAAO,OAAO,cAAc,EAAE,OAAO,qBAAqB;AAAA,MACjE;AACK,WAAA,SAAS,IAAIe,eAAA,QAAM,QAAQ;AAChC,WAAK,cAAc;AAEnB,YAAM,KAAK,4BAA4B;AAAA,aAChC,OAAO;AACd,YAAM,MAAM,KAAK;AAAA,IAAA;AAAA,EACnB;AAAA,EAGF,IAAI,QAAiB;AACf,QAAA,CAAC,KAAK,aAAa;AACrB,YAAM,KAAK,gCAAgC;AACpC,aAAA;AAAA,IAAA;AAGF,WAAA;AAAA,EAAA;AAAA,EAGT,MAAM,IAAI,KAAkC;AACtC,QAAA,CAAC,KAAK,MAAc,QAAA;AAEjB,WAAA,YAAY,MAAM,KAAK,OAAO,IAAI,GAAG,GAAG,KAAK,mBAAmB,EACpE,KAAK,CAAC,SAAU,OAAO,KAAK,MAAM,IAAI,IAAI,IAAK,EAC/C,MAAM,CAAC,UAAU;AAChB,YAAM,MAAM,oBAAoB,OAAO,WAAW,KAAK,EAAE;AAClD,aAAA;AAAA,IAAA,CACR;AAAA,EAAA;AAAA,EAGL,MAAM,IAAI,KAAa,KAA+B;AAChD,QAAA,CAAC,KAAK,MAAc,QAAA;AAEpB,QAAA;AACI,YAAA,MAAM,OAAO,KAAK,OAAO,OAAO,cAAc,EAAE,OAAO,KAAK,CAAC;AAC7D,YAAA,aAAa,KAAK,UAAU,GAAG;AACrC,UAAI,MAAM,GAAG;AACX,cAAM,KAAK,OAAO,IAAI,KAAK,YAAY,MAAM,GAAG;AAAA,MAAA,OAC3C;AACL,cAAM,KAAK,OAAO,IAAI,KAAK,UAAU;AAAA,MAAA;AAEhC,aAAA;AAAA,aACA,OAAO;AACR,YAAA,MAAM,oBAAoB,KAAK,EAAE;AAChC,aAAA;AAAA,IAAA;AAAA,EACT;AAAA,EAGF,MAAM,IAAI,KAAkC;AACtC,QAAA,CAAC,KAAK,MAAc,QAAA;AAEpB,QAAA;AACI,YAAA,KAAK,sBAAsB,GAAG,EAAE;AAChC,YAAA,KAAK,OAAO,IAAI,GAAG;AAClB,aAAA;AAAA,aACA,OAAO;AACR,YAAA,MAAM,oBAAoB,KAAK,EAAE;AAChC,aAAA;AAAA,IAAA;AAAA,EACT;AAAA,EAGF,MAAM,OAAiC;AACjC,QAAA,CAAC,KAAK,MAAc,QAAA;AAEpB,QAAA;AACF,YAAM,OAAO,MAAM,KAAK,OAAO,KAAK,GAAG;AAChC,aAAA;AAAA,aACA,OAAO;AACR,YAAA,MAAM,qBAAqB,KAAK,EAAE;AACjC,aAAA;AAAA,IAAA;AAAA,EACT;AAAA,EAGF,MAAM,QAA6B;AAC7B,QAAA,CAAC,KAAK,MAAc,QAAA;AAEpB,QAAA;AACF,YAAM,KAAK,yBAAyB;AAC9B,YAAA,KAAK,OAAO,QAAQ;AACnB,aAAA;AAAA,aACA,OAAO;AACR,YAAA,MAAM,sBAAsB,KAAK,EAAE;AAClC,aAAA;AAAA,IAAA;AAAA,EACT;AAAA,EAGF,MAAM,cAAc,SAAkC;AAC9C,UAAA,OAAO,MAAM,KAAK,KAAK;AAC7B,QAAI,CAAC,KAAM;AAEX,UAAM,WAAW,KAAK,OAAO,CAAC,QAAQ,QAAQ,KAAK,CAAC,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC;AAClE,UAAA,QAAQ,IAAI,SAAS,IAAI,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC,CAAC;AAAA,EAAA;AAE1D;AC9Ga,MAAA,uBAAuB,CAACf,YAAuC;AAC1E,QAAM,eAAeA,QAAO,OAAO,cAAc,EAAE,OAAO,UAAU,KAAK;AAEnE,QAAA,KAAK,4BAA4B,YAAY,EAAE;AAEjD,MAAA;AAEJ,UAAQ,cAAc;AAAA,IACpB,KAAK;AACQ,iBAAA,IAAI,mBAAmBA,OAAM;AACxC;AAAA,IACF;AACa,iBAAA,IAAI,sBAAsBA,OAAM;AAC3C;AAAA,EAAA;AAGG,SAAA;AACT;AClBA,MAAM,UAAU,CAAC,EAAE,QAAAA,cAAoD;AACrE,MAAI,WAAiC;AAE9B,SAAA;AAAA,IACL,mBAAmB;AACjB,UAAI,CAAC,UAAU;AACb,cAAM,KAAK,oDAAoD;AAC/D,mBAAW,qBAAqBA,OAAM;AAAA,MAAA;AAEjC,aAAA;AAAA,IAAA;AAAA,EAEX;AACF;AAEA,MAAe,WAAA;AAAA,EACb;AACF;ACJA,MAAe,QAAA;AAAA,EACb;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EAAC;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../server/src/utils/log.ts","../../server/src/utils/invalidateCache.ts","../../server/src/permissions.ts","../../server/src/bootstrap.ts","../../server/src/utils/key.ts","../../server/src/utils/body.ts","../../server/src/middlewares/cache.ts","../../server/src/middlewares/graphql.ts","../../server/src/middlewares/index.ts","../../server/src/register.ts","../../server/src/config/index.ts","../../server/src/content-types/index.ts","../../server/src/controllers/controller.ts","../../server/src/controllers/index.ts","../../server/src/policies/index.ts","../../server/src/routes/purge.ts","../../server/src/routes/index.ts","../../server/src/utils/withTimeout.ts","../../server/src/services/memory/provider.ts","../../server/src/services/redis/provider.ts","../../server/src/services/resolver.ts","../../server/src/services/index.ts","../../server/src/index.ts"],"sourcesContent":["export const loggy = {\n info: (msg: string) => {\n const shouldDebug = strapi.plugin('strapi-cache').config('debug') ?? false;\n if (!shouldDebug) {\n return;\n }\n strapi.log.info(`[STRAPI CACHE] ${msg}`);\n },\n error: (msg: string) => {\n const shouldDebug = strapi.plugin('strapi-cache').config('debug') ?? false;\n if (!shouldDebug) {\n return;\n }\n strapi.log.error(`[STRAPI CACHE] ${msg}`);\n },\n warn: (msg: string) => {\n const shouldDebug = strapi.plugin('strapi-cache').config('debug') ?? false;\n if (!shouldDebug) {\n return;\n }\n strapi.log.warn(`[STRAPI CACHE] ${msg}`);\n },\n};\n","import { Core } from '@strapi/strapi';\nimport { CacheProvider } from 'src/types/cache.types';\nimport { loggy } from './log';\n\nexport async function invalidateCache(event: any, cacheStore: CacheProvider, strapi: Core.Strapi) {\n const { model } = event;\n const uid = model.uid;\n\n try {\n const contentType = strapi.contentType(uid);\n\n if (!contentType || !contentType.kind) {\n loggy.info(`Content type ${uid} not found`);\n return;\n }\n\n const pluralName =\n contentType.kind === 'singleType'\n ? contentType.info.singularName\n : contentType.info.pluralName;\n const apiPath = `/api/${pluralName}`;\n const regex = new RegExp(`^.*:${apiPath}(/.*)?(\\\\?.*)?$`);\n\n await cacheStore.clearByRegexp([regex]);\n loggy.info(`Invalidated cache for ${apiPath}`);\n } catch (error) {\n loggy.error('Cache invalidation error:');\n loggy.error(error);\n }\n}\n\nexport async function invalidateGraphqlCache(\n event: any,\n cacheStore: CacheProvider,\n strapi: Core.Strapi\n) {\n try {\n const graphqlRegex = new RegExp(`^POST:\\/graphql(:.*)?$`);\n\n await cacheStore.clearByRegexp([graphqlRegex]);\n loggy.info(`Invalidated cache for ${graphqlRegex}`);\n } catch (error) {\n loggy.error('Cache invalidation error:');\n loggy.error(error);\n }\n}\n","export const actions = [\n {\n section: 'plugins',\n displayName: 'Purge Cache',\n uid: 'purge-cache',\n pluginName: 'strapi-cache',\n },\n];\n","import type { Core } from '@strapi/strapi';\nimport { invalidateCache, invalidateGraphqlCache } from './utils/invalidateCache';\nimport { CacheService } from './types/cache.types';\nimport { loggy } from './utils/log';\nimport { actions } from './permissions';\n\nconst bootstrap = ({ strapi }: { strapi: Core.Strapi }) => {\n loggy.info('Initializing');\n try {\n const cacheService = strapi.plugin('strapi-cache').services.service as CacheService;\n const cacheStore = cacheService.getCacheInstance();\n cacheStore.init();\n\n strapi.db.lifecycles.subscribe({\n async afterCreate(event) {\n await invalidateCache(event, cacheStore, strapi);\n await invalidateGraphqlCache(event, cacheStore, strapi);\n },\n async afterUpdate(event) {\n await invalidateCache(event, cacheStore, strapi);\n await invalidateGraphqlCache(event, cacheStore, strapi);\n },\n async afterDelete(event) {\n await invalidateCache(event, cacheStore, strapi);\n await invalidateGraphqlCache(event, cacheStore, strapi);\n },\n });\n\n if (!cacheStore) {\n loggy.error('Plugin could not be initialized');\n return;\n }\n } catch (error) {\n loggy.error('Plugin could not be initialized');\n return;\n }\n loggy.info('Plugin initialized');\n\n strapi.admin.services.permission.actionProvider.registerMany(actions);\n};\n\nexport default bootstrap;\n","import { createHash } from 'crypto';\nimport { Context } from 'koa';\n\nexport const generateCacheKey = (context: Context) => {\n const { url } = context.request;\n const { method } = context.request;\n\n return `${method}:${url}`;\n};\n\nexport const generateGraphqlCacheKey = (payload: string) => {\n const hash = createHash('sha256').update(payload).digest('base64url');\n return `POST:/graphql:${hash}`;\n};\n","import { Stream } from 'stream';\nimport { createGunzip, createBrotliDecompress, createInflate } from 'zlib';\n\nexport const streamToBuffer = (stream: Stream): Promise<Buffer> => {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n stream.on('data', (chunk) => chunks.push(chunk));\n stream.on('end', () => resolve(Buffer.concat(chunks)));\n stream.on('error', reject);\n });\n};\n\nexport const decompressBuffer = async (buffer: Buffer, encoding?: string): Promise<Buffer> => {\n return new Promise((resolve, reject) => {\n let decompressStream;\n switch (encoding) {\n case 'gzip':\n decompressStream = createGunzip();\n break;\n case 'br':\n decompressStream = createBrotliDecompress();\n break;\n case 'deflate':\n decompressStream = createInflate();\n break;\n default:\n return resolve(buffer);\n }\n\n const chunks: Buffer[] = [];\n decompressStream.on('data', (chunk) => chunks.push(chunk));\n decompressStream.on('end', () => resolve(Buffer.concat(chunks)));\n decompressStream.on('error', reject);\n\n decompressStream.end(buffer);\n });\n};\n\nexport const decodeBufferToText = (buffer: Buffer): string => {\n const decoder = new TextDecoder('utf-8');\n return decoder.decode(buffer);\n};\n","import { Context } from 'koa';\nimport { generateCacheKey } from '../utils/key';\nimport { CacheService } from '../../src/types/cache.types';\nimport { loggy } from '../utils/log';\nimport Stream from 'stream';\nimport { decodeBufferToText, decompressBuffer, streamToBuffer } from '../../src/utils/body';\n\nconst middleware = async (ctx: Context, next: any) => {\n const cacheService = strapi.plugin('strapi-cache').services.service as CacheService;\n const cacheableRoutes = strapi.plugin('strapi-cache').config('cacheableRoutes') as string[];\n const cacheHeaders = strapi.plugin('strapi-cache').config('cacheHeaders') as boolean;\n const cacheAuthorizedRequests = strapi\n .plugin('strapi-cache')\n .config('cacheAuthorizedRequests') as boolean;\n const cacheStore = cacheService.getCacheInstance();\n const { url } = ctx.request;\n const key = generateCacheKey(ctx);\n const cacheEntry = await cacheStore.get(key);\n const cacheControlHeader = ctx.request.headers['cache-control'];\n const noCache = cacheControlHeader && cacheControlHeader.includes('no-cache');\n const routeIsCachable =\n cacheableRoutes.some((route) => url.startsWith(route)) ||\n (cacheableRoutes.length === 0 && url.startsWith('/api'));\n const authorizationHeader = ctx.request.headers['authorization'];\n\n if (authorizationHeader && !cacheAuthorizedRequests) {\n loggy.info(`Authorized request bypassing cache: ${key}`);\n await next();\n return;\n }\n\n if (cacheEntry && !noCache) {\n loggy.info(`HIT with key: ${key}`);\n ctx.status = 200;\n ctx.body = cacheEntry.body;\n if (cacheHeaders) {\n ctx.set(cacheEntry.headers);\n }\n return;\n }\n\n await next();\n\n if (ctx.method === 'GET' && ctx.status >= 200 && ctx.status < 300 && routeIsCachable) {\n loggy.info(`MISS with key: ${key}`);\n\n if (ctx.body instanceof Stream) {\n const buf = await streamToBuffer(ctx.body);\n const contentEncoding = ctx.response.headers['content-encoding'];\n const decompressed = await decompressBuffer(buf, contentEncoding);\n const responseText = decodeBufferToText(decompressed);\n\n const headersToStore = cacheHeaders ? ctx.response.headers : null;\n await cacheStore.set(key, { body: responseText, headers: headersToStore });\n ctx.body = buf;\n } else {\n const headersToStore = cacheHeaders ? ctx.response.headers : null;\n await cacheStore.set(key, { body: ctx.body, headers: headersToStore });\n }\n }\n};\n\nexport default middleware;\n","import rawBody from 'raw-body';\nimport { generateGraphqlCacheKey } from '../utils/key';\nimport Stream, { Readable } from 'stream';\nimport { loggy } from '../utils/log';\nimport { CacheService } from '../../src/types/cache.types';\nimport { decodeBufferToText, decompressBuffer, streamToBuffer } from '../../src/utils/body';\n\nconst middleware = async (ctx: any, next: any) => {\n const cacheService = strapi.plugin('strapi-cache').services.service as CacheService;\n const cacheHeaders = strapi.plugin('strapi-cache').config('cacheHeaders') as boolean;\n const cacheAuthorizedRequests = strapi\n .plugin('strapi-cache')\n .config('cacheAuthorizedRequests') as boolean;\n const cacheStore = cacheService.getCacheInstance();\n const { url } = ctx.request;\n\n const originalReq = ctx.req;\n const bodyBuffer = await rawBody(originalReq);\n const body = bodyBuffer.toString();\n\n const clonedReq = new Readable();\n clonedReq.push(bodyBuffer);\n clonedReq.push(null);\n\n (clonedReq as any).headers = { ...originalReq.headers };\n (clonedReq as any).method = originalReq.method;\n (clonedReq as any).url = originalReq.url;\n (clonedReq as any).httpVersion = originalReq.httpVersion;\n (clonedReq as any).socket = originalReq.socket;\n (clonedReq as any).connection = originalReq.connection;\n\n ctx.req = clonedReq;\n ctx.request.req = clonedReq;\n\n const isIntrospectionQuery = body.includes('IntrospectionQuery');\n if (isIntrospectionQuery) {\n loggy.info('Skipping cache for introspection query');\n await next();\n return;\n }\n\n const key = generateGraphqlCacheKey(body);\n const cacheEntry = await cacheStore.get(key);\n const cacheControlHeader = ctx.request.headers['cache-control'];\n const noCache = cacheControlHeader && cacheControlHeader.includes('no-cache');\n const authorizationHeader = ctx.request.headers['authorization'];\n\n if (authorizationHeader && !cacheAuthorizedRequests) {\n loggy.info(`Authorized request bypassing cache: ${key}`);\n await next();\n return;\n }\n\n if (cacheEntry && !noCache) {\n loggy.info(`HIT with key: ${key}`);\n ctx.status = 200;\n ctx.body = cacheEntry.body;\n if (cacheHeaders) {\n ctx.set(cacheEntry.headers);\n }\n return;\n }\n\n await next();\n\n if (\n ctx.method === 'POST' &&\n ctx.status >= 200 &&\n ctx.status < 300 &&\n url.startsWith('/graphql')\n ) {\n loggy.info(`MISS with key: ${key}`);\n const headers = ctx.request.headers;\n const authorizationHeader = headers['authorization'];\n if (authorizationHeader && !cacheAuthorizedRequests) {\n loggy.info(`Authorized request not caching: ${key}`);\n return;\n }\n\n if (ctx.body instanceof Stream) {\n const buf = await streamToBuffer(ctx.body);\n const contentEncoding = ctx.response.headers['content-encoding']; // e.g., gzip, br, deflate\n const decompressed = await decompressBuffer(buf, contentEncoding);\n const responseText = decodeBufferToText(decompressed);\n\n const headersToStore = cacheHeaders ? ctx.response.headers : null;\n await cacheStore.set(key, { body: responseText, headers: headersToStore });\n ctx.body = buf;\n } else {\n const headersToStore = cacheHeaders ? ctx.response.headers : null;\n await cacheStore.set(key, {\n body: ctx.body,\n headers: headersToStore,\n });\n }\n }\n};\n\nexport default middleware;\n","import cache from './cache';\nimport graphql from './graphql';\n\nexport default {\n graphql,\n cache,\n};\n","import type { Core } from '@strapi/strapi';\nimport middlewares from './middlewares';\n\nconst register = ({ strapi }: { strapi: Core.Strapi }) => {\n strapi.server.use(middlewares.cache);\n strapi.server.use(middlewares.graphql);\n};\n\nexport default register;\n","export default {\n default: ({ env }) => ({\n debug: false,\n max: 1000,\n ttl: 1000 * 60 * 60,\n size: 1024 * 1014 * 10,\n allowStale: false,\n cacheableRoutes: [],\n provider: 'memory',\n redisConfig: env('REDIS_URL'),\n cacheHeaders: true,\n cacheAuthorizedRequests: false,\n cacheGetTimeoutInMs: 1000,\n }),\n validator: (config) => {\n if (typeof config.debug !== 'boolean') {\n throw new Error(`Invalid config: debug must be a boolean`);\n }\n if (typeof config.max !== 'number') {\n throw new Error(`Invalid config: max must be a number`);\n }\n if (typeof config.ttl !== 'number') {\n throw new Error(`Invalid config: ttl must be a number`);\n }\n if (typeof config.size !== 'number') {\n throw new Error(`Invalid config: size must be a number`);\n }\n if (typeof config.allowStale !== 'boolean') {\n throw new Error(`Invalid config: allowStale must be a boolean`);\n }\n if (\n !Array.isArray(config.cacheableRoutes) ||\n config.cacheableRoutes.some((item) => typeof item !== 'string')\n ) {\n throw new Error(`Invalid config: cacheableRoutes must be an string array`);\n }\n if (typeof config.provider !== 'string') {\n throw new Error(`Invalid config: provider must be a string`);\n }\n if (config.provider !== 'memory' && config.provider !== 'redis') {\n throw new Error(`Invalid config: provider must be 'memory' or 'redis'`);\n }\n if (\n config.provider === 'redis' &&\n !config.redisConfig &&\n (typeof config.redisConfig !== 'string' || typeof config.redisConfig !== 'object')\n ) {\n throw new Error(`Invalid config: redisConfig must be set when using redis provider`);\n }\n if (typeof config.cacheHeaders !== 'boolean') {\n throw new Error(`Invalid config: cacheHeaders must be a boolean`);\n }\n if (typeof config.cacheAuthorizedRequests !== 'boolean') {\n throw new Error(`Invalid config: cacheAuthorizedRequests must be a boolean`);\n }\n\n if (typeof config.cacheGetTimeoutInMs !== 'number') {\n throw new Error(`Invalid config: cacheGetTimeoutInMs must be a number`);\n }\n },\n};\n","export default {};\n","import type { Core } from '@strapi/strapi';\nimport { Context } from 'koa';\nimport { CacheService } from 'src/types/cache.types';\n\nconst controller = ({ strapi }: { strapi: Core.Strapi }) => ({\n async purgeCache(ctx: Context) {\n const service = strapi.plugin('strapi-cache').service('service') as CacheService;\n\n await service.getCacheInstance().reset();\n\n ctx.body = {\n message: 'Cache purged successfully',\n };\n },\n async purgeCacheByKey(ctx: Context) {\n const { key } = ctx.params;\n const service = strapi.plugin('strapi-cache').service('service') as CacheService;\n const regex = new RegExp(`(^|\\/)${key}(\\/|\\\\?|$)`);\n\n await service.getCacheInstance().clearByRegexp([regex]);\n\n ctx.body = {\n message: `Cache purged successfully for key: ${key}`,\n };\n },\n async cacheableRoutes(ctx: Context) {\n const cacheableRoutes = strapi.plugin('strapi-cache').config('cacheableRoutes');\n ctx.body = cacheableRoutes;\n },\n});\n\nexport default controller;\n","import controller from './controller';\n\nexport default {\n controller,\n};\n","export default {};\n","export default [\n {\n method: 'POST',\n path: '/purge-cache',\n handler: 'controller.purgeCache',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'plugin::content-manager.hasPermissions',\n config: {\n actions: ['plugin::strapi-cache.purge-cache'],\n },\n },\n ],\n },\n },\n {\n method: 'POST',\n path: '/purge-cache/:key',\n handler: 'controller.purgeCacheByKey',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'plugin::content-manager.hasPermissions',\n config: {\n actions: ['plugin::strapi-cache.purge-cache'],\n },\n },\n ],\n },\n },\n {\n method: 'GET',\n path: '/cacheable-routes',\n handler: 'controller.cacheableRoutes',\n config: {\n policies: [\n 'admin::isAuthenticatedAdmin',\n {\n name: 'plugin::content-manager.hasPermissions',\n config: {\n actions: ['plugin::strapi-cache.purge-cache'],\n },\n },\n ],\n },\n },\n];\n","import purgeRoute from './purge';\n\nconst routes = {\n 'purge-route': {\n type: 'admin',\n routes: purgeRoute,\n },\n};\n\nexport default routes;\n","export const withTimeout = (callback: () => Promise<any>, ms: number) => {\n let timeout: NodeJS.Timeout | null = null;\n\n return Promise.race([\n callback().then((result) => {\n if (timeout) {\n clearTimeout(timeout);\n }\n return result;\n }),\n new Promise((_, reject) => {\n timeout = setTimeout(() => {\n reject(new Error('timeout'));\n }, ms);\n }),\n ]);\n};\n","import type { Core } from '@strapi/strapi';\nimport { LRUCache } from 'lru-cache';\nimport { withTimeout } from '../../utils/withTimeout';\nimport { CacheProvider, CacheService } from '../../types/cache.types';\nimport { loggy } from '../../utils/log';\n\nexport class InMemoryCacheProvider implements CacheProvider {\n private initialized = false;\n private provider!: LRUCache<string, any>;\n private cacheGetTimeoutInMs: number;\n\n constructor(private strapi: Core.Strapi) {}\n\n init(): void {\n if (this.initialized) {\n loggy.error('Provider already initialized');\n return;\n }\n\n this.initialized = true;\n\n const max = Number(this.strapi.plugin('strapi-cache').config('max'));\n const ttl = Number(this.strapi.plugin('strapi-cache').config('ttl'));\n const size = Number(this.strapi.plugin('strapi-cache').config('size'));\n const allowStale = Boolean(this.strapi.plugin('strapi-cache').config('allowStale'));\n\n this.provider = new LRUCache({\n max,\n ttl,\n size,\n allowStale,\n });\n\n this.cacheGetTimeoutInMs = Number(\n this.strapi.plugin('strapi-cache').config('cacheGetTimeoutInMs')\n );\n\n loggy.info('Provider initialized');\n }\n\n get ready(): boolean {\n if (!this.initialized) {\n loggy.info('Provider not initialized');\n return false;\n }\n\n return true;\n }\n\n async get(key: string): Promise<any | null> {\n if (!this.ready) return null;\n\n return withTimeout(\n () =>\n new Promise((resolve) => {\n resolve(this.provider.get(key));\n }),\n this.cacheGetTimeoutInMs\n ).catch((error) => {\n loggy.error(`Error during get: ${error?.message || error}`);\n return null;\n });\n }\n\n async set(key: string, val: any): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n return this.provider.set(key, val);\n } catch (error) {\n loggy.error(`Error during set: ${error}`);\n return null;\n }\n }\n\n async del(key: string): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n loggy.info(`PURGING KEY: ${key}`);\n return this.provider.delete(key);\n } catch (error) {\n loggy.error(`Error during delete: ${error}`);\n return null;\n }\n }\n\n async keys(): Promise<string[] | null> {\n if (!this.ready) return null;\n\n try {\n return Array.from(this.provider.keys());\n } catch (error) {\n loggy.error(`Error fetching keys: ${error}`);\n return null;\n }\n }\n\n async reset(): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n const allKeys = await this.keys();\n if (!allKeys) return null;\n\n loggy.info(`PURGING ALL KEYS: ${allKeys.length}`);\n await Promise.all(allKeys.map((key) => this.del(key)));\n return true;\n } catch (error) {\n loggy.error(`Error during reset: ${error}`);\n return null;\n }\n }\n\n async clearByRegexp(regExps: RegExp[]): Promise<void> {\n const keys = (await this.keys()) || [];\n const matches = keys.filter((key) => regExps.some((re) => re.test(key)));\n await Promise.all(matches.map((key) => this.del(key)));\n }\n}\n","import type { Core } from '@strapi/strapi';\nimport Redis from 'ioredis';\nimport { withTimeout } from '../../utils/withTimeout';\nimport { CacheProvider } from '../../types/cache.types';\nimport { loggy } from '../../utils/log';\n\nexport class RedisCacheProvider implements CacheProvider {\n private initialized = false;\n private client!: Redis;\n private cacheGetTimeoutInMs: number;\n\n constructor(private strapi: Core.Strapi) {}\n\n init(): void {\n if (this.initialized) {\n loggy.error('Redis provider already initialized');\n return;\n }\n try {\n const redisUrl =\n this.strapi.plugin('strapi-cache').config('redisConfig') || 'redis://localhost:6379';\n this.cacheGetTimeoutInMs = Number(\n this.strapi.plugin('strapi-cache').config('cacheGetTimeoutInMs')\n );\n this.client = new Redis(redisUrl);\n this.initialized = true;\n\n loggy.info('Redis provider initialized');\n } catch (error) {\n loggy.error(error);\n }\n }\n\n get ready(): boolean {\n if (!this.initialized) {\n loggy.info('Redis provider not initialized');\n return false;\n }\n\n return true;\n }\n\n async get(key: string): Promise<any | null> {\n if (!this.ready) return null;\n\n return withTimeout(() => this.client.get(key), this.cacheGetTimeoutInMs)\n .then((data) => (data ? JSON.parse(data) : null))\n .catch((error) => {\n loggy.error(`Redis get error: ${error?.message || error}`);\n return null;\n });\n }\n\n async set(key: string, val: any): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n const ttl = Number(this.strapi.plugin('strapi-cache').config('ttl'));\n const serialized = JSON.stringify(val);\n if (ttl > 0) {\n await this.client.set(key, serialized, 'EX', ttl);\n } else {\n await this.client.set(key, serialized);\n }\n return val;\n } catch (error) {\n loggy.error(`Redis set error: ${error}`);\n return null;\n }\n }\n\n async del(key: string): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n loggy.info(`Redis PURGING KEY: ${key}`);\n await this.client.del(key);\n return true;\n } catch (error) {\n loggy.error(`Redis del error: ${error}`);\n return null;\n }\n }\n\n async keys(): Promise<string[] | null> {\n if (!this.ready) return null;\n\n try {\n const keys = await this.client.keys('*');\n return keys;\n } catch (error) {\n loggy.error(`Redis keys error: ${error}`);\n return null;\n }\n }\n\n async reset(): Promise<any | null> {\n if (!this.ready) return null;\n\n try {\n loggy.info(`Redis FLUSHING ALL KEYS`);\n await this.client.flushdb();\n return true;\n } catch (error) {\n loggy.error(`Redis reset error: ${error}`);\n return null;\n }\n }\n\n async clearByRegexp(regExps: RegExp[]): Promise<void> {\n const keys = await this.keys();\n if (!keys) return;\n\n const toDelete = keys.filter((key) => regExps.some((re) => re.test(key)));\n await Promise.all(toDelete.map((key) => this.del(key)));\n }\n}\n","import type { Core } from '@strapi/strapi';\nimport { InMemoryCacheProvider } from './memory/provider';\nimport { RedisCacheProvider } from './redis/provider';\nimport { CacheProvider } from '../../src/types/cache.types';\nimport { loggy } from '../../src/utils/log';\n\nexport const resolveCacheProvider = (strapi: Core.Strapi): CacheProvider => {\n const providerType = strapi.plugin('strapi-cache').config('provider') || 'memory';\n\n loggy.info(`Selected cache provider: ${providerType}`);\n\n let instance: CacheProvider;\n\n switch (providerType) {\n case 'redis':\n instance = new RedisCacheProvider(strapi);\n break;\n default:\n instance = new InMemoryCacheProvider(strapi);\n break;\n }\n\n return instance;\n};\n","import type { Core } from '@strapi/strapi';\nimport { resolveCacheProvider } from './resolver';\nimport { CacheProvider, CacheService } from '../../src/types/cache.types';\nimport { loggy } from '../../src/utils/log';\n\nconst service = ({ strapi }: { strapi: Core.Strapi }): CacheService => {\n let instance: null | CacheProvider = null;\n\n return {\n getCacheInstance() {\n if (!instance) {\n loggy.info('Initializing cache service from provider config...');\n instance = resolveCacheProvider(strapi);\n }\n return instance;\n },\n };\n};\n\nexport default {\n service,\n};\n","/**\n * Application methods\n */\nimport bootstrap from './bootstrap';\nimport register from './register';\n\n/**\n * Plugin server methods\n */\nimport config from './config';\nimport contentTypes from './content-types';\nimport controllers from './controllers';\nimport middlewares from './middlewares';\nimport policies from './policies';\nimport routes from './routes';\nimport services from './services';\n\nexport default {\n register,\n bootstrap,\n destroy() {},\n config,\n controllers,\n routes,\n services,\n contentTypes,\n policies,\n middlewares,\n};\n"],"names":["strapi","middleware","authorizationHeader","graphql","cache","config","service"],"mappings":"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"}
|