next-fetch-panel 0.1.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.
@@ -0,0 +1,23 @@
1
+ declare const dynamic = "force-dynamic";
2
+ type GuardFn = (request: Request) => Response | null | undefined | void | Promise<Response | null | undefined | void>;
3
+ /**
4
+ * Returns a Next.js Route Handler GET function for the SSE stream.
5
+ * Use the guard option to add authentication or any other access control:
6
+ *
7
+ * export const dynamic = "force-dynamic"
8
+ * export const GET = createDevPanelRoute({
9
+ * guard: (request) => {
10
+ * const token = request.headers.get("authorization")
11
+ * if (!isValidToken(token)) return new Response("Forbidden", { status: 403 })
12
+ * },
13
+ * })
14
+ *
15
+ * For simple use with no access control:
16
+ * export { dynamic, GET } from "@/server-network-panel/route"
17
+ */
18
+ declare function createDevPanelRoute(options?: {
19
+ guard?: GuardFn;
20
+ }): (request: Request) => Promise<Response>;
21
+ declare const GET: (request: Request) => Promise<Response>;
22
+
23
+ export { GET, createDevPanelRoute, dynamic };
package/dist/route.js ADDED
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/route.ts
21
+ var route_exports = {};
22
+ __export(route_exports, {
23
+ GET: () => GET,
24
+ createDevPanelRoute: () => createDevPanelRoute,
25
+ dynamic: () => dynamic
26
+ });
27
+ module.exports = __toCommonJS(route_exports);
28
+ var import_headers = require("next/headers");
29
+
30
+ // src/store.ts
31
+ var BUFFER_SIZE = 100;
32
+ function createStore() {
33
+ const subscribers = /* @__PURE__ */ new Set();
34
+ const buffer = [];
35
+ return {
36
+ push(entry) {
37
+ buffer.push(entry);
38
+ if (buffer.length > BUFFER_SIZE) buffer.shift();
39
+ subscribers.forEach((fn) => fn(entry));
40
+ },
41
+ subscribe(fn) {
42
+ subscribers.add(fn);
43
+ return () => subscribers.delete(fn);
44
+ },
45
+ getBuffer() {
46
+ return buffer.slice();
47
+ }
48
+ };
49
+ }
50
+ var devLogStore = globalThis.__devLogStore ?? (globalThis.__devLogStore = createStore());
51
+
52
+ // src/route.ts
53
+ var dynamic = "force-dynamic";
54
+ function createDevPanelRoute(options) {
55
+ return async function GET2(request) {
56
+ const blocked = await options?.guard?.(request);
57
+ if (blocked instanceof Response) return blocked;
58
+ const sessionId = (await (0, import_headers.headers)()).get("x-dev-sid");
59
+ let unsubscribe;
60
+ const stream = new ReadableStream({
61
+ start(controller) {
62
+ const encoder = new TextEncoder();
63
+ const encode = (entry) => encoder.encode(`data: ${JSON.stringify(entry)}
64
+
65
+ `);
66
+ for (const entry of devLogStore.getBuffer()) {
67
+ if (entry.sessionId === sessionId) controller.enqueue(encode(entry));
68
+ }
69
+ unsubscribe = devLogStore.subscribe((entry) => {
70
+ if (entry.sessionId !== sessionId) return;
71
+ try {
72
+ controller.enqueue(encode(entry));
73
+ } catch {
74
+ }
75
+ });
76
+ },
77
+ cancel() {
78
+ unsubscribe?.();
79
+ }
80
+ });
81
+ return new Response(stream, {
82
+ headers: {
83
+ "Content-Type": "text/event-stream",
84
+ "Cache-Control": "no-cache",
85
+ Connection: "keep-alive"
86
+ }
87
+ });
88
+ };
89
+ }
90
+ var GET = createDevPanelRoute();
91
+ // Annotate the CommonJS export names for ESM import in node:
92
+ 0 && (module.exports = {
93
+ GET,
94
+ createDevPanelRoute,
95
+ dynamic
96
+ });
package/dist/route.mjs ADDED
@@ -0,0 +1,69 @@
1
+ // src/route.ts
2
+ import { headers } from "next/headers";
3
+
4
+ // src/store.ts
5
+ var BUFFER_SIZE = 100;
6
+ function createStore() {
7
+ const subscribers = /* @__PURE__ */ new Set();
8
+ const buffer = [];
9
+ return {
10
+ push(entry) {
11
+ buffer.push(entry);
12
+ if (buffer.length > BUFFER_SIZE) buffer.shift();
13
+ subscribers.forEach((fn) => fn(entry));
14
+ },
15
+ subscribe(fn) {
16
+ subscribers.add(fn);
17
+ return () => subscribers.delete(fn);
18
+ },
19
+ getBuffer() {
20
+ return buffer.slice();
21
+ }
22
+ };
23
+ }
24
+ var devLogStore = globalThis.__devLogStore ?? (globalThis.__devLogStore = createStore());
25
+
26
+ // src/route.ts
27
+ var dynamic = "force-dynamic";
28
+ function createDevPanelRoute(options) {
29
+ return async function GET2(request) {
30
+ const blocked = await options?.guard?.(request);
31
+ if (blocked instanceof Response) return blocked;
32
+ const sessionId = (await headers()).get("x-dev-sid");
33
+ let unsubscribe;
34
+ const stream = new ReadableStream({
35
+ start(controller) {
36
+ const encoder = new TextEncoder();
37
+ const encode = (entry) => encoder.encode(`data: ${JSON.stringify(entry)}
38
+
39
+ `);
40
+ for (const entry of devLogStore.getBuffer()) {
41
+ if (entry.sessionId === sessionId) controller.enqueue(encode(entry));
42
+ }
43
+ unsubscribe = devLogStore.subscribe((entry) => {
44
+ if (entry.sessionId !== sessionId) return;
45
+ try {
46
+ controller.enqueue(encode(entry));
47
+ } catch {
48
+ }
49
+ });
50
+ },
51
+ cancel() {
52
+ unsubscribe?.();
53
+ }
54
+ });
55
+ return new Response(stream, {
56
+ headers: {
57
+ "Content-Type": "text/event-stream",
58
+ "Cache-Control": "no-cache",
59
+ Connection: "keep-alive"
60
+ }
61
+ });
62
+ };
63
+ }
64
+ var GET = createDevPanelRoute();
65
+ export {
66
+ GET,
67
+ createDevPanelRoute,
68
+ dynamic
69
+ };
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "next-fetch-panel",
3
+ "version": "0.1.0",
4
+ "description": "Real-time server-side fetch inspector panel for Next.js App Router",
5
+ "keywords": [
6
+ "nextjs",
7
+ "devtools",
8
+ "fetch",
9
+ "inspector",
10
+ "panel",
11
+ "server-components",
12
+ "ssr",
13
+ "debugging"
14
+ ],
15
+ "license": "MIT",
16
+ "sideEffects": false,
17
+ "main": "./dist/index.js",
18
+ "module": "./dist/index.mjs",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.mjs",
24
+ "require": "./dist/index.js"
25
+ },
26
+ "./patch": {
27
+ "types": "./dist/patch.d.ts",
28
+ "import": "./dist/patch.mjs",
29
+ "require": "./dist/patch.js"
30
+ },
31
+ "./middleware": {
32
+ "types": "./dist/middleware.d.ts",
33
+ "import": "./dist/middleware.mjs",
34
+ "require": "./dist/middleware.js"
35
+ },
36
+ "./route": {
37
+ "types": "./dist/route.d.ts",
38
+ "import": "./dist/route.mjs",
39
+ "require": "./dist/route.js"
40
+ }
41
+ },
42
+ "files": [
43
+ "dist",
44
+ "README.md"
45
+ ],
46
+ "scripts": {
47
+ "build": "tsup",
48
+ "dev": "tsup --watch",
49
+ "type-check": "tsc --noEmit"
50
+ },
51
+ "peerDependencies": {
52
+ "next": ">=15.0.0",
53
+ "react": ">=19.0.0",
54
+ "react-dom": ">=19.0.0",
55
+ "tailwindcss": ">=4.0.0"
56
+ },
57
+ "dependencies": {
58
+ "@base-ui/react": "^1.0.0",
59
+ "class-variance-authority": "^0.7.0",
60
+ "clsx": "^2.0.0",
61
+ "lucide-react": "^1.0.0",
62
+ "react-resizable-panels": "^4.0.0",
63
+ "tailwind-merge": "^3.0.0"
64
+ },
65
+ "devDependencies": {
66
+ "@types/node": "^20.0.0",
67
+ "@types/react": "^19.0.0",
68
+ "@types/react-dom": "^19.0.0",
69
+ "tsup": "^8.0.0",
70
+ "typescript": "^5.0.0"
71
+ }
72
+ }