next-cache-toolbar 0.1.2 → 0.2.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.
Files changed (33) hide show
  1. package/dist/cjs/{cache-entry-client-Cg2-NRrZ.js → cache-entry-client-C0CjMKC5.js} +11 -12
  2. package/dist/cjs/cache-panel-context-client-FIUru-uB.js +115 -0
  3. package/dist/cjs/cache-panel-head-client-Cs4uyFh7.js +139 -0
  4. package/dist/cjs/cache-panel-table-client-9aBv-MjJ.js +22 -0
  5. package/dist/cjs/{cache-panel-trigger-client-ChZncD_2.js → cache-panel-trigger-client-CGeo22Q8.js} +2 -2
  6. package/dist/cjs/{cache-panel-wrapper-client-DE5QrmN0.js → cache-panel-wrapper-client-2eJisZgJ.js} +2 -2
  7. package/dist/cjs/cache-refresh-data-client-VWar7JpG.js +48 -0
  8. package/dist/cjs/{dialog-client-AZHsTC7l.js → dialog-client-ChHtZVMD.js} +16 -16
  9. package/dist/cjs/getCacheEntries-server-BheTh0n9.js +72 -0
  10. package/dist/cjs/index.d.ts +13 -1
  11. package/dist/cjs/index.js +19 -86
  12. package/dist/es/{cache-entry-client-CtWrVYTN.js → cache-entry-client-Ceh-eYDl.js} +11 -14
  13. package/dist/es/cache-panel-context-client-DCXKayLF.js +110 -0
  14. package/dist/es/cache-panel-head-client-BBfig3xH.js +120 -0
  15. package/dist/es/cache-panel-table-client-C9YfopmF.js +22 -0
  16. package/dist/es/{cache-panel-trigger-client-GrlxjSO5.js → cache-panel-trigger-client-CGReagL-.js} +2 -2
  17. package/dist/es/{cache-panel-wrapper-client-BosTuysv.js → cache-panel-wrapper-client-Cv0HcuJC.js} +2 -2
  18. package/dist/es/cache-refresh-data-client-BjsJkQ5H.js +48 -0
  19. package/dist/es/{dialog-client-D5Q_DDEF.js → dialog-client-C319YNfG.js} +1 -1
  20. package/dist/es/getCacheEntries-server-CgNUCSp3.js +72 -0
  21. package/dist/es/index.d.mts +13 -1
  22. package/dist/es/index.mjs +18 -85
  23. package/dist/style.css +1 -2
  24. package/package.json +15 -9
  25. package/readme.md +4 -0
  26. package/dist/cjs/cache-panel-context-client-B1EgwMzI.js +0 -33
  27. package/dist/cjs/cache-panel-head-client-CbhKAPhZ.js +0 -46
  28. package/dist/cjs/cache-panel-table-client-CuP76AwU.js +0 -56
  29. package/dist/cjs/refresh-data-button-client-D4e_gWso.js +0 -28
  30. package/dist/es/cache-panel-context-client-D5NKXXpF.js +0 -28
  31. package/dist/es/cache-panel-head-client-CZC6pddt.js +0 -46
  32. package/dist/es/cache-panel-table-client-Qc84cSj6.js +0 -56
  33. package/dist/es/refresh-data-button-client-DaxVafNg.js +0 -28
@@ -2,11 +2,10 @@
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import { cva } from 'class-variance-authority';
4
4
  import * as React from 'react';
5
- import { useMemo } from 'react';
6
5
  import { clsx } from 'clsx';
7
6
  import { twMerge } from 'tailwind-merge';
8
7
  import { Slot } from '@radix-ui/react-slot';
9
- import { D as Dialog, a as DialogTrigger, b as DialogContent } from './dialog-client-D5Q_DDEF.js';
8
+ import { D as Dialog, a as DialogTrigger, b as DialogContent } from './dialog-client-C319YNfG.js';
10
9
  import { Braces } from 'lucide-react';
11
10
  import JsonView from 'react18-json-view';
12
11
 
@@ -121,18 +120,16 @@ const Button = /*#__PURE__*/ React.forwardRef(({ className, variant, size, asChi
121
120
  });
122
121
  Button.displayName = "Button";
123
122
 
123
+ const getEntryRevalidateLeft = (cacheEntry)=>{
124
+ if (!cacheEntry.data?.headers.date || !cacheEntry.revalidate) {
125
+ return;
126
+ }
127
+ const cacheEntryDate = new Date(cacheEntry.data?.headers.date);
128
+ const msDiff = new Date().getTime() - cacheEntryDate.getTime();
129
+ return Math.floor(cacheEntry.revalidate - msDiff / 1000);
130
+ };
124
131
  const CacheEntry = (props)=>{
125
- const cacheEntryRevalidateLeft = useMemo(()=>{
126
- if (!props.cacheEntry.data?.headers.date || !props.cacheEntry.revalidate) {
127
- return;
128
- }
129
- const cacheEntryDate = new Date(props.cacheEntry.data?.headers.date);
130
- const msDiff = new Date().getTime() - cacheEntryDate.getTime();
131
- return Math.floor(props.cacheEntry.revalidate - msDiff / 1000);
132
- }, [
133
- props.cacheEntry.data?.headers.date,
134
- props.cacheEntry.revalidate
135
- ]);
132
+ const cacheEntryRevalidateLeft = getEntryRevalidateLeft(props.cacheEntry);
136
133
  const isStale = cacheEntryRevalidateLeft ? cacheEntryRevalidateLeft < 0 : false;
137
134
  return /*#__PURE__*/ jsxs(TableRow, {
138
135
  children: [
@@ -183,4 +180,4 @@ const CacheEntry = (props)=>{
183
180
  });
184
181
  };
185
182
 
186
- export { Button as B, CacheEntry as C, TableHead as T, TableBody as a, Table as b, cn as c, TableHeader as d, TableRow as e };
183
+ export { Button as B, CacheEntry as C, TableHead as T, TableBody as a, TableRow as b, cn as c, TableCell as d, Table as e, TableHeader as f };
@@ -0,0 +1,110 @@
1
+ 'use client';
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import React__default, { useState, useMemo, createContext } from 'react';
4
+
5
+ const CachePanelContext = /*#__PURE__*/ createContext({
6
+ entries: [],
7
+ isOpen: false,
8
+ setEntries: ()=>{},
9
+ toggleOpen: ()=>{},
10
+ setSorting: ()=>{},
11
+ addFilter: ()=>{},
12
+ clearFilter: ()=>{}
13
+ });
14
+ const sortCacheEntryByKey = (key, a, b)=>{
15
+ switch(key){
16
+ case "url":
17
+ if (!a.data || !b.data) {
18
+ return 0;
19
+ }
20
+ return a.data.url.localeCompare(b.data.url);
21
+ case "revalidate":
22
+ return (a.revalidate ?? 0) - (b.revalidate ?? 0);
23
+ case "tags":
24
+ if (a.tags.length === 0 || b.tags.length === 0) {
25
+ return 0;
26
+ }
27
+ return a.tags[0]?.localeCompare(b.tags[0] ?? "") ?? 0;
28
+ case "timestamp":
29
+ {
30
+ if (!a.data?.headers.date || !b.data?.headers.date) {
31
+ return 0;
32
+ }
33
+ return new Date(b.data.headers.date).getTime() - new Date(a.data.headers.date).getTime();
34
+ }
35
+ }
36
+ };
37
+ const useCachePanelContext = ()=>React__default.useContext(CachePanelContext);
38
+ const CachePanelContextProvider = (props)=>{
39
+ const [isOpen, setIsOpen] = useState(false);
40
+ const [entries, setEntries] = useState(props.entries);
41
+ const [filters, setFilters] = useState();
42
+ const [sorting, setSorting] = useState(undefined);
43
+ const toggleOpen = ()=>{
44
+ setIsOpen(!isOpen);
45
+ };
46
+ const addFilter = (key, value)=>{
47
+ setFilters((prev)=>{
48
+ if (!prev) {
49
+ return {
50
+ [key]: value
51
+ };
52
+ }
53
+ return {
54
+ ...prev,
55
+ [key]: value
56
+ };
57
+ });
58
+ };
59
+ const clearFilter = (key)=>{
60
+ setFilters((prev)=>{
61
+ if (!prev) {
62
+ return;
63
+ }
64
+ delete prev[key];
65
+ return prev;
66
+ });
67
+ };
68
+ const derivedEntries = useMemo(()=>{
69
+ let copiedEntries = entries.slice();
70
+ if (filters) {
71
+ copiedEntries = copiedEntries.filter((entry)=>{
72
+ const { tags: tagsFilter, url: urlFilter } = filters;
73
+ if (tagsFilter && !entry[1].tags.some((tag)=>tag.match(tagsFilter))) {
74
+ return false;
75
+ }
76
+ if (urlFilter && !entry[1].data.url.match(urlFilter)) {
77
+ return false;
78
+ }
79
+ return true;
80
+ });
81
+ }
82
+ if (!sorting) {
83
+ return copiedEntries;
84
+ }
85
+ const { key, direction } = sorting;
86
+ return copiedEntries.toSorted((a, b)=>{
87
+ return sortCacheEntryByKey(key, a[1], b[1]) * (direction === "asc" ? 1 : -1);
88
+ });
89
+ }, [
90
+ entries,
91
+ sorting,
92
+ filters
93
+ ]);
94
+ return /*#__PURE__*/ jsx(CachePanelContext.Provider, {
95
+ value: {
96
+ isOpen,
97
+ toggleOpen,
98
+ setSorting,
99
+ sorting,
100
+ entries: derivedEntries,
101
+ setEntries,
102
+ filters,
103
+ addFilter,
104
+ clearFilter
105
+ },
106
+ children: props.children
107
+ });
108
+ };
109
+
110
+ export { CachePanelContextProvider as C, useCachePanelContext as u };
@@ -0,0 +1,120 @@
1
+ 'use client';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { c as cn, T as TableHead, B as Button } from './cache-entry-client-Ceh-eYDl.js';
4
+ import * as React from 'react';
5
+ import { useState, useCallback, useMemo } from 'react';
6
+ import { ArrowDownAZIcon, ArrowUpAZIcon, FilterIcon } from 'lucide-react';
7
+ import { u as useCachePanelContext } from './cache-panel-context-client-DCXKayLF.js';
8
+
9
+ const Input = /*#__PURE__*/ React.forwardRef(({ className, type, ...props }, ref)=>{
10
+ return /*#__PURE__*/ jsx("input", {
11
+ type: type,
12
+ className: cn("nct-flex nct-h-10 nct-w-full nct-rounded-md nct-border nct-border-input nct-bg-background nct-px-3 nct-py-2 nct-text-sm nct-ring-offset-background file:nct-border-0 file:nct-bg-transparent file:nct-text-sm file:nct-font-medium placeholder:nct-text-muted-foreground focus-visible:nct-outline-none focus-visible:nct-ring-2 focus-visible:nct-ring-ring focus-visible:nct-ring-offset-2 disabled:nct-cursor-not-allowed disabled:nct-opacity-50", className),
13
+ ref: ref,
14
+ ...props
15
+ });
16
+ });
17
+ Input.displayName = "Input";
18
+
19
+ const CachePanelHead = ({ sortingProperty, children, className, withFilter = false, ...props })=>{
20
+ const { setSorting, sorting, filters, addFilter, clearFilter } = useCachePanelContext();
21
+ const [filterInputVisible, setFilterInputVisible] = useState(false);
22
+ const inputRef = useCallback((node)=>{
23
+ if (!node) {
24
+ return;
25
+ }
26
+ node.focus();
27
+ }, []);
28
+ const sortingDirection = useMemo(()=>{
29
+ if (!sorting || sorting.key !== sortingProperty) {
30
+ return;
31
+ }
32
+ return sorting.direction;
33
+ }, [
34
+ sorting,
35
+ sortingProperty
36
+ ]);
37
+ const filterValue = useMemo(()=>{
38
+ if (sortingProperty !== "url" && sortingProperty !== "tags") {
39
+ return;
40
+ }
41
+ return filters?.[sortingProperty] ?? "";
42
+ }, [
43
+ sortingProperty,
44
+ filters
45
+ ]);
46
+ const onHeadClick = ()=>{
47
+ if (sorting && sorting.key === sortingProperty) {
48
+ setSorting({
49
+ key: sortingProperty,
50
+ direction: sorting.direction === "asc" ? "desc" : "asc"
51
+ });
52
+ } else {
53
+ setSorting({
54
+ key: sortingProperty,
55
+ direction: "asc"
56
+ });
57
+ }
58
+ };
59
+ const onFilterInputKeyDown = (event)=>{
60
+ if (sortingProperty !== "url" && sortingProperty !== "tags") {
61
+ return;
62
+ }
63
+ // clear value on esc
64
+ if (event.key === "Escape") {
65
+ clearFilter(sortingProperty);
66
+ setFilterInputVisible(false);
67
+ }
68
+ };
69
+ const onFilterInputChange = (event)=>{
70
+ if (sortingProperty !== "url" && sortingProperty !== "tags") {
71
+ return;
72
+ }
73
+ addFilter(sortingProperty, event.target.value);
74
+ };
75
+ const onFilterInputBlur = (event)=>{
76
+ if (sortingProperty !== "url" && sortingProperty !== "tags") {
77
+ return;
78
+ }
79
+ if (event.target.value === "") {
80
+ setFilterInputVisible(false);
81
+ }
82
+ };
83
+ return /*#__PURE__*/ jsx(TableHead, {
84
+ className: cn("group", className),
85
+ ...props,
86
+ children: /*#__PURE__*/ jsxs("div", {
87
+ className: cn("nct-flex nct-items-center nct-gap-2 nct-py-2", sorting?.key === sortingProperty && "nct-underline"),
88
+ children: [
89
+ /*#__PURE__*/ jsx("div", {
90
+ onClick: onHeadClick,
91
+ onKeyDown: onHeadClick,
92
+ children: children
93
+ }),
94
+ sortingDirection === "asc" && /*#__PURE__*/ jsx(ArrowDownAZIcon, {}),
95
+ sortingDirection === "desc" && /*#__PURE__*/ jsx(ArrowUpAZIcon, {}),
96
+ withFilter && /*#__PURE__*/ jsxs("div", {
97
+ className: "ml-auto",
98
+ children: [
99
+ !filterInputVisible && /*#__PURE__*/ jsx(Button, {
100
+ variant: "ghost",
101
+ size: "icon",
102
+ className: cn(),
103
+ onClick: ()=>setFilterInputVisible(true),
104
+ children: /*#__PURE__*/ jsx(FilterIcon, {})
105
+ }),
106
+ filterInputVisible && /*#__PURE__*/ jsx(Input, {
107
+ onKeyDown: onFilterInputKeyDown,
108
+ value: filterValue,
109
+ onChange: onFilterInputChange,
110
+ onBlur: onFilterInputBlur,
111
+ ref: inputRef
112
+ })
113
+ ]
114
+ })
115
+ ]
116
+ })
117
+ });
118
+ };
119
+
120
+ export { CachePanelHead as C };
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { a as TableBody, b as TableRow, d as TableCell, C as CacheEntry } from './cache-entry-client-Ceh-eYDl.js';
4
+ import { u as useCachePanelContext } from './cache-panel-context-client-DCXKayLF.js';
5
+
6
+ const CachePanelTable = ()=>{
7
+ const { entries } = useCachePanelContext();
8
+ return /*#__PURE__*/ jsxs(TableBody, {
9
+ children: [
10
+ entries.length === 0 && /*#__PURE__*/ jsx(TableRow, {
11
+ children: /*#__PURE__*/ jsx(TableCell, {
12
+ children: "No cache entries"
13
+ })
14
+ }),
15
+ entries.map(([file, cacheEntry])=>/*#__PURE__*/ jsx(CacheEntry, {
16
+ cacheEntry: cacheEntry
17
+ }, file))
18
+ ]
19
+ });
20
+ };
21
+
22
+ export { CachePanelTable as C };
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { B as Button } from './cache-entry-client-CtWrVYTN.js';
3
+ import { B as Button } from './cache-entry-client-Ceh-eYDl.js';
4
4
  import 'react';
5
- import { u as useCachePanelContext } from './cache-panel-context-client-D5NKXXpF.js';
5
+ import { u as useCachePanelContext } from './cache-panel-context-client-DCXKayLF.js';
6
6
 
7
7
  function CachePanelTrigger(props) {
8
8
  const { toggleOpen } = useCachePanelContext();
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { b as Table } from './cache-entry-client-CtWrVYTN.js';
3
+ import { e as Table } from './cache-entry-client-Ceh-eYDl.js';
4
4
  import 'react';
5
- import { u as useCachePanelContext } from './cache-panel-context-client-D5NKXXpF.js';
5
+ import { u as useCachePanelContext } from './cache-panel-context-client-DCXKayLF.js';
6
6
 
7
7
  const CacheTable = (props)=>{
8
8
  const { isOpen } = useCachePanelContext();
@@ -0,0 +1,48 @@
1
+ 'use client';
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { g as getCacheFiles } from './getCacheEntries-server-CgNUCSp3.js';
4
+ import { B as Button, c as cn } from './cache-entry-client-Ceh-eYDl.js';
5
+ import { Loader2 } from 'lucide-react';
6
+ import { usePathname } from 'next/navigation';
7
+ import { useTransition, useEffect } from 'react';
8
+ import { u as useCachePanelContext } from './cache-panel-context-client-DCXKayLF.js';
9
+
10
+ function RefreshDataButton({ enabled, interval }) {
11
+ const { setEntries } = useCachePanelContext();
12
+ const [isPending, startTransition] = useTransition();
13
+ const pathname = usePathname();
14
+ const refreshData = ()=>{
15
+ startTransition(async ()=>{
16
+ const files = await getCacheFiles();
17
+ setEntries(files ?? []);
18
+ });
19
+ };
20
+ useEffect(()=>{
21
+ console.log("pathname changed", pathname);
22
+ refreshData();
23
+ }, [
24
+ pathname
25
+ ]);
26
+ useEffect(()=>{
27
+ if (!enabled) {
28
+ return;
29
+ }
30
+ const intervalId = setInterval(refreshData, interval);
31
+ return ()=>clearInterval(intervalId);
32
+ }, [
33
+ enabled,
34
+ interval
35
+ ]);
36
+ return /*#__PURE__*/ jsx(Button, {
37
+ variant: "outline",
38
+ size: "icon",
39
+ onClick: refreshData,
40
+ children: /*#__PURE__*/ jsx(Loader2, {
41
+ className: cn("nct-h-4 nct-w-4", {
42
+ "nct-animate-spin": isPending
43
+ })
44
+ })
45
+ });
46
+ }
47
+
48
+ export { RefreshDataButton as R };
@@ -3,7 +3,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import * as DialogPrimitive from '@radix-ui/react-dialog';
4
4
  import { X } from 'lucide-react';
5
5
  import * as React from 'react';
6
- import { c as cn } from './cache-entry-client-CtWrVYTN.js';
6
+ import { c as cn } from './cache-entry-client-Ceh-eYDl.js';
7
7
 
8
8
  const Dialog = DialogPrimitive.Root;
9
9
  const DialogTrigger = DialogPrimitive.Trigger;
@@ -0,0 +1,72 @@
1
+ 'use server';
2
+ import { existsSync, promises } from 'fs';
3
+ import { z, ZodError } from 'zod';
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 };
@@ -1,5 +1,17 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
- declare function NextCacheToolbar(): Promise<react_jsx_runtime.JSX.Element>;
3
+ type Props = {
4
+ /**
5
+ * If true, the cache table will automatically refresh when the pathname changes.
6
+ * @default false
7
+ */
8
+ autoRefresh?: boolean;
9
+ /**
10
+ * The interval in milliseconds to refresh the cache table.
11
+ * @default 10000
12
+ */
13
+ interval?: number;
14
+ };
15
+ declare function NextCacheToolbar({ autoRefresh, interval, }: Props): Promise<react_jsx_runtime.JSX.Element>;
4
16
 
5
17
  export { NextCacheToolbar };
package/dist/es/index.mjs CHANGED
@@ -1,91 +1,21 @@
1
- 'use server';
2
1
  import { jsx, jsxs } from 'react/jsx-runtime';
3
- import { d as TableHeader, e as TableRow, T as TableHead } from './cache-entry-client-CtWrVYTN.js';
4
2
  import { Braces, PanelBottomCloseIcon } from 'lucide-react';
5
- import { existsSync } from 'fs';
6
- import { readdir, readFile } from 'node:fs/promises';
7
- import { z, ZodError } from 'zod';
8
- import { C as CachePanelContextProvider } from './cache-panel-context-client-D5NKXXpF.js';
9
- import { C as CachePanelHead } from './cache-panel-head-client-CZC6pddt.js';
10
- import { C as CachePanelTable } from './cache-panel-table-client-Qc84cSj6.js';
11
- import { C as CachePanelTrigger } from './cache-panel-trigger-client-GrlxjSO5.js';
12
- import { C as CacheTable } from './cache-panel-wrapper-client-BosTuysv.js';
13
- import { R as RefreshDataButton } from './refresh-data-button-client-DaxVafNg.js';
3
+ import { g as getCacheFiles } from './getCacheEntries-server-CgNUCSp3.js';
4
+ import { f as TableHeader, b as TableRow, T as TableHead } from './cache-entry-client-Ceh-eYDl.js';
5
+ import { C as CachePanelContextProvider } from './cache-panel-context-client-DCXKayLF.js';
6
+ import { C as CachePanelTable } from './cache-panel-table-client-C9YfopmF.js';
7
+ import { C as CachePanelTrigger } from './cache-panel-trigger-client-CGReagL-.js';
8
+ import { C as CacheTable } from './cache-panel-wrapper-client-Cv0HcuJC.js';
9
+ import { R as RefreshDataButton } from './cache-refresh-data-client-BjsJkQ5H.js';
10
+ import { C as CachePanelHead } from './cache-panel-head-client-BBfig3xH.js';
14
11
 
15
- const stringToJSONSchema = z.string().transform((str, ctx)=>{
16
- try {
17
- return JSON.parse(str);
18
- } catch (e) {
19
- ctx.addIssue({
20
- code: "custom",
21
- message: "Encoded body is not in JSON format",
22
- path: [
23
- "data",
24
- "body"
25
- ]
26
- });
27
- return z.NEVER;
28
- }
29
- });
30
- const nextCacheFileSchema = z.object({
31
- data: z.object({
32
- body: z.string(),
33
- headers: z.record(z.string(), z.string()),
34
- status: z.number(),
35
- url: z.string()
36
- }),
37
- kind: z.union([
38
- z.literal("FETCH"),
39
- z.unknown()
40
- ]),
41
- revalidate: z.number().optional(),
42
- tags: z.array(z.string()).optional().default([])
43
- }).transform((cacheEntry)=>{
44
- const body = stringToJSONSchema.parse(atob(cacheEntry.data.body));
45
- return {
46
- ...cacheEntry,
47
- data: {
48
- ...cacheEntry.data,
49
- body
50
- }
51
- };
52
- });
53
-
54
- const cachePath = ".next/cache/fetch-cache";
55
- const getCacheFiles = async ()=>{
56
- if (!existsSync(cachePath)) {
57
- return;
58
- }
59
- const files = await readdir(cachePath);
60
- const cacheFiles = new Map();
61
- for (const file of files){
62
- // ignore tags-manifest file
63
- if (file.match(/manifest/)) {
64
- continue;
65
- }
66
- try {
67
- const fileContent = await readFile(`${cachePath}/${file}`);
68
- const cacheEntry = nextCacheFileSchema.parse(JSON.parse(fileContent.toString()));
69
- cacheFiles.set(file, cacheEntry);
70
- } catch (error) {
71
- if (error instanceof ZodError) {
72
- const issues = error.issues;
73
- console.error(`File ${file} do not match the schema`, issues);
74
- continue;
75
- }
76
- console.error(`Error parsing ${file}`);
77
- }
78
- }
79
- return cacheFiles;
80
- };
81
-
82
- async function NextCacheToolbar() {
12
+ async function NextCacheToolbar({ autoRefresh = false, interval = 10000 }) {
83
13
  const files = await getCacheFiles();
84
- const cacheEntries = Array.from(files?.entries() ?? []);
85
14
  return /*#__PURE__*/ jsx("div", {
86
15
  id: "next-cache-toolbar",
87
16
  className: "nct-text-primary nct-font-mono",
88
17
  children: /*#__PURE__*/ jsxs(CachePanelContextProvider, {
18
+ entries: files ?? [],
89
19
  children: [
90
20
  /*#__PURE__*/ jsx(CachePanelTrigger, {
91
21
  className: "nct-fixed nct-rounded-full nct-bottom-4 nct-right-4 nct-bg-gradient-to-r nct-from-fuchsia-500 nct-to-cyan-500",
@@ -100,14 +30,16 @@ async function NextCacheToolbar() {
100
30
  /*#__PURE__*/ jsx(CachePanelHead, {
101
31
  sortingProperty: "url",
102
32
  className: "nct-w-[300px]",
33
+ withFilter: true,
103
34
  children: "URL"
104
35
  }),
105
36
  /*#__PURE__*/ jsx(CachePanelHead, {
106
37
  sortingProperty: "revalidate",
107
- children: "Revalidate"
38
+ children: "Revalidate (ms)"
108
39
  }),
109
40
  /*#__PURE__*/ jsx(CachePanelHead, {
110
41
  sortingProperty: "tags",
42
+ withFilter: true,
111
43
  children: "Tags"
112
44
  }),
113
45
  /*#__PURE__*/ jsx(CachePanelHead, {
@@ -119,7 +51,10 @@ async function NextCacheToolbar() {
119
51
  children: /*#__PURE__*/ jsxs("div", {
120
52
  className: "nct-flex nct-items-center nct-justify-end nct-gap-2",
121
53
  children: [
122
- /*#__PURE__*/ jsx(RefreshDataButton, {}),
54
+ /*#__PURE__*/ jsx(RefreshDataButton, {
55
+ enabled: autoRefresh,
56
+ interval: interval
57
+ }),
123
58
  /*#__PURE__*/ jsx(CachePanelTrigger, {
124
59
  children: /*#__PURE__*/ jsx(PanelBottomCloseIcon, {})
125
60
  })
@@ -129,9 +64,7 @@ async function NextCacheToolbar() {
129
64
  ]
130
65
  })
131
66
  }),
132
- /*#__PURE__*/ jsx(CachePanelTable, {
133
- entries: cacheEntries
134
- })
67
+ /*#__PURE__*/ jsx(CachePanelTable, {})
135
68
  ]
136
69
  })
137
70
  ]