next-cache-toolbar 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/{cache-entry-client-C0CjMKC5.js → cache-entry-client-BlFbLrtq.js} +34 -22
- package/dist/cjs/{cache-panel-context-client-FIUru-uB.js → cache-panel-context-client-CkDMJX2-.js} +7 -1
- package/dist/cjs/{cache-panel-head-client-Cs4uyFh7.js → cache-panel-head-client-BqfBWPpR.js} +30 -21
- package/dist/cjs/{cache-panel-table-client-9aBv-MjJ.js → cache-panel-table-client-DBvA6vo5.js} +2 -2
- package/dist/cjs/{cache-panel-trigger-client-CGeo22Q8.js → cache-panel-trigger-client-0RzTHzAT.js} +2 -3
- package/dist/cjs/{cache-panel-wrapper-client-puZq7rcV.js → cache-panel-wrapper-client-DTI35uJg.js} +2 -3
- package/dist/cjs/cache-purge-button-client-CXGIDomZ.js +25 -0
- package/dist/cjs/{cache-refresh-data-client-CrvqEMoX.js → cache-refresh-data-client-DIPw0IhW.js} +5 -6
- package/dist/cjs/{dialog-client-ChHtZVMD.js → dialog-client-eJy2OUEG.js} +18 -16
- package/dist/cjs/getCacheEntries-server-Bq5gM82M.js +104 -0
- package/dist/cjs/index.d.ts +11 -1
- package/dist/cjs/index.js +15 -12
- package/dist/cjs/purge-cache-server-GmkiFGoN.js +12 -0
- package/dist/es/{cache-entry-client-Ceh-eYDl.js → cache-entry-client-Bk7a0rFQ.mjs} +34 -22
- package/dist/es/{cache-panel-context-client-DCXKayLF.js → cache-panel-context-client-DlqXZGzO.mjs} +7 -1
- package/dist/es/{cache-panel-head-client-BBfig3xH.js → cache-panel-head-client-DTReOdNO.mjs} +15 -6
- package/dist/es/{cache-panel-table-client-C9YfopmF.js → cache-panel-table-client-B844eHwF.mjs} +2 -2
- package/dist/es/{cache-panel-trigger-client-CGReagL-.js → cache-panel-trigger-client-CbXiKLEx.mjs} +2 -3
- package/dist/es/{cache-panel-wrapper-client-CjKNX-hk.js → cache-panel-wrapper-client-Dcmlm3kc.mjs} +2 -3
- package/dist/es/cache-purge-button-client-CN9H6t8R.mjs +25 -0
- package/dist/es/{cache-refresh-data-client-Cb9wMeZh.js → cache-refresh-data-client-CX8rfbFV.mjs} +5 -6
- package/dist/es/{dialog-client-C319YNfG.js → dialog-client-D8kKKnZH.mjs} +2 -2
- package/dist/es/getCacheEntries-server-eY7FwQMw.mjs +104 -0
- package/dist/es/index.d.mts +11 -1
- package/dist/es/index.mjs +16 -13
- package/dist/es/purge-cache-server-Dd41_99d.mjs +12 -0
- package/dist/style.css +1 -1
- package/package.json +84 -84
- package/readme.md +32 -5
- package/dist/cjs/getCacheEntries-server-DMz68ZTt.js +0 -72
- package/dist/es/getCacheEntries-server-BkR7kA29.js +0 -72
package/readme.md
CHANGED
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
A toolbar that helps to identify [data cache](https://nextjs.org/docs/app/building-your-application/caching#data-cache) entries
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|
|
|
7
|
-
|
|
7
|
+

|
|
8
8
|
|
|
9
|
-

|
|
10
|
+
## How to use it?
|
|
12
11
|
|
|
13
12
|
`next-cache-toolbar` requires to use [app router](https://nextjs.org/docs/app/building-your-application/caching#data-cache)
|
|
14
13
|
|
|
@@ -44,3 +43,31 @@ export default function Layout({ children }) {
|
|
|
44
43
|
);
|
|
45
44
|
}
|
|
46
45
|
```
|
|
46
|
+
|
|
47
|
+
## How does `data cache` work?
|
|
48
|
+
|
|
49
|
+
There are two cases when `data cache` is used:
|
|
50
|
+
- wrapping any function with `unstable_cache`
|
|
51
|
+
- adding `next` options to `fetch` call
|
|
52
|
+
|
|
53
|
+
Both cases will store returned data inside `.next/cache/fetch-cache` folder in format
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"kind": "FETCH",
|
|
58
|
+
"revalidate": 30,
|
|
59
|
+
"tags": [],
|
|
60
|
+
"data": {
|
|
61
|
+
"body": "...",
|
|
62
|
+
"headers": {},
|
|
63
|
+
"status": 200,
|
|
64
|
+
"url": "..."
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
There is one caveat, when using `unstable_cache` stored data will do not have any headers while body will be in plain JSON.
|
|
70
|
+
But when using `fetch` with `next` options all headers from response will be present and `body` will be encoded using base64.
|
|
71
|
+
Nevertheless both of these approaches stores all data as well as `revalidate` time and `tags`.
|
|
72
|
+
|
|
73
|
+
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
'use server';
|
|
2
|
-
var zod = require('zod');
|
|
3
|
-
var node_fs = require('node:fs');
|
|
4
|
-
|
|
5
|
-
const stringToJSONSchema = zod.z.string().transform((str, ctx)=>{
|
|
6
|
-
try {
|
|
7
|
-
return JSON.parse(str);
|
|
8
|
-
} catch (e) {
|
|
9
|
-
ctx.addIssue({
|
|
10
|
-
code: "custom",
|
|
11
|
-
message: "Encoded body is not in JSON format",
|
|
12
|
-
path: [
|
|
13
|
-
"data",
|
|
14
|
-
"body"
|
|
15
|
-
]
|
|
16
|
-
});
|
|
17
|
-
return zod.z.NEVER;
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
const nextCacheFileSchema = zod.z.object({
|
|
21
|
-
data: zod.z.object({
|
|
22
|
-
body: zod.z.string(),
|
|
23
|
-
headers: zod.z.record(zod.z.string(), zod.z.string()),
|
|
24
|
-
status: zod.z.number(),
|
|
25
|
-
url: zod.z.string()
|
|
26
|
-
}),
|
|
27
|
-
kind: zod.z.union([
|
|
28
|
-
zod.z.literal("FETCH"),
|
|
29
|
-
zod.z.unknown()
|
|
30
|
-
]),
|
|
31
|
-
revalidate: zod.z.number().optional(),
|
|
32
|
-
tags: zod.z.array(zod.z.string()).optional().default([])
|
|
33
|
-
}).transform((cacheEntry)=>{
|
|
34
|
-
const body = stringToJSONSchema.parse(atob(cacheEntry.data.body));
|
|
35
|
-
return {
|
|
36
|
-
...cacheEntry,
|
|
37
|
-
data: {
|
|
38
|
-
...cacheEntry.data,
|
|
39
|
-
body
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const cachePath = ".next/cache/fetch-cache";
|
|
45
|
-
const getCacheFiles = async ()=>{
|
|
46
|
-
if (!node_fs.existsSync(cachePath)) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
const files = await node_fs.promises.readdir(cachePath);
|
|
50
|
-
const cacheFiles = new Map();
|
|
51
|
-
for (const file of files){
|
|
52
|
-
// ignore tags-manifest file
|
|
53
|
-
if (file.match(/manifest/)) {
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
const fileContent = await node_fs.promises.readFile(`${cachePath}/${file}`);
|
|
58
|
-
const cacheEntry = nextCacheFileSchema.parse(JSON.parse(fileContent.toString()));
|
|
59
|
-
cacheFiles.set(file, cacheEntry);
|
|
60
|
-
} catch (error) {
|
|
61
|
-
if (error instanceof zod.ZodError) {
|
|
62
|
-
const issues = error.issues;
|
|
63
|
-
console.error(`File ${file} do not match the schema`, issues);
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
console.error(`Error parsing ${file}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return Array.from(cacheFiles.entries());
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
exports.getCacheFiles = getCacheFiles;
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
'use server';
|
|
2
|
-
import { z, ZodError } from 'zod';
|
|
3
|
-
import { existsSync, promises } from 'node:fs';
|
|
4
|
-
|
|
5
|
-
const stringToJSONSchema = z.string().transform((str, ctx)=>{
|
|
6
|
-
try {
|
|
7
|
-
return JSON.parse(str);
|
|
8
|
-
} catch (e) {
|
|
9
|
-
ctx.addIssue({
|
|
10
|
-
code: "custom",
|
|
11
|
-
message: "Encoded body is not in JSON format",
|
|
12
|
-
path: [
|
|
13
|
-
"data",
|
|
14
|
-
"body"
|
|
15
|
-
]
|
|
16
|
-
});
|
|
17
|
-
return z.NEVER;
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
const nextCacheFileSchema = z.object({
|
|
21
|
-
data: z.object({
|
|
22
|
-
body: z.string(),
|
|
23
|
-
headers: z.record(z.string(), z.string()),
|
|
24
|
-
status: z.number(),
|
|
25
|
-
url: z.string()
|
|
26
|
-
}),
|
|
27
|
-
kind: z.union([
|
|
28
|
-
z.literal("FETCH"),
|
|
29
|
-
z.unknown()
|
|
30
|
-
]),
|
|
31
|
-
revalidate: z.number().optional(),
|
|
32
|
-
tags: z.array(z.string()).optional().default([])
|
|
33
|
-
}).transform((cacheEntry)=>{
|
|
34
|
-
const body = stringToJSONSchema.parse(atob(cacheEntry.data.body));
|
|
35
|
-
return {
|
|
36
|
-
...cacheEntry,
|
|
37
|
-
data: {
|
|
38
|
-
...cacheEntry.data,
|
|
39
|
-
body
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const cachePath = ".next/cache/fetch-cache";
|
|
45
|
-
const getCacheFiles = async ()=>{
|
|
46
|
-
if (!existsSync(cachePath)) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
const files = await promises.readdir(cachePath);
|
|
50
|
-
const cacheFiles = new Map();
|
|
51
|
-
for (const file of files){
|
|
52
|
-
// ignore tags-manifest file
|
|
53
|
-
if (file.match(/manifest/)) {
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
const fileContent = await promises.readFile(`${cachePath}/${file}`);
|
|
58
|
-
const cacheEntry = nextCacheFileSchema.parse(JSON.parse(fileContent.toString()));
|
|
59
|
-
cacheFiles.set(file, cacheEntry);
|
|
60
|
-
} catch (error) {
|
|
61
|
-
if (error instanceof ZodError) {
|
|
62
|
-
const issues = error.issues;
|
|
63
|
-
console.error(`File ${file} do not match the schema`, issues);
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
console.error(`Error parsing ${file}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return Array.from(cacheFiles.entries());
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
export { getCacheFiles as g };
|