@nexttrace/devtools 0.1.0 → 0.1.2

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 (3) hide show
  1. package/dist/index.js +100 -20
  2. package/dist/index.mjs +100 -20
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -384,25 +384,56 @@ var import_react = require("react");
384
384
  var import_jsx_runtime2 = require("react/jsx-runtime");
385
385
  var JsonViewer = ({ data, theme }) => {
386
386
  const [copied, setCopied] = (0, import_react.useState)(false);
387
+ const [showRawRsc, setShowRawRsc] = (0, import_react.useState)(false);
387
388
  const t = tokens[theme];
388
- const handleCopy = () => {
389
- const text = typeof data === "string" ? data : JSON.stringify(data, null, 2);
390
- navigator.clipboard.writeText(text);
391
- setCopied(true);
392
- setTimeout(() => setCopied(false), 1500);
393
- };
394
389
  let parsed = data;
395
390
  let isJson = false;
391
+ let isRsc = false;
392
+ let rscData = null;
396
393
  if (typeof data === "string") {
397
394
  try {
398
395
  parsed = JSON.parse(data);
399
396
  isJson = true;
400
397
  } catch {
401
- isJson = false;
398
+ const lines = data.split("\n");
399
+ for (const line of lines) {
400
+ const colonIdx = line.indexOf(":");
401
+ if (colonIdx > 0 && colonIdx < 10) {
402
+ const prefix = line.substring(0, colonIdx).trim();
403
+ if (/^[0-9a-f]+$/i.test(prefix)) {
404
+ const body = line.substring(colonIdx + 1).trim();
405
+ if (body.startsWith("{") || body.startsWith("[")) {
406
+ try {
407
+ const candidate = JSON.parse(body);
408
+ if (candidate && typeof candidate === "object") {
409
+ if (typeof candidate.a === "string" && String(candidate.a).startsWith("$")) {
410
+ continue;
411
+ }
412
+ rscData = candidate;
413
+ isRsc = true;
414
+ }
415
+ } catch {
416
+ }
417
+ }
418
+ }
419
+ }
420
+ }
421
+ if (isRsc && !showRawRsc && rscData !== null) {
422
+ parsed = rscData;
423
+ isJson = true;
424
+ } else {
425
+ isJson = false;
426
+ }
402
427
  }
403
428
  } else if (data !== null && typeof data === "object") {
404
429
  isJson = true;
405
430
  }
431
+ const handleCopy = () => {
432
+ const text = isRsc && !showRawRsc && rscData !== null ? JSON.stringify(rscData, null, 2) : typeof data === "string" ? data : JSON.stringify(data, null, 2);
433
+ navigator.clipboard.writeText(text);
434
+ setCopied(true);
435
+ setTimeout(() => setCopied(false), 1500);
436
+ };
406
437
  const renderValue = (val, depth = 0) => {
407
438
  if (val === null) {
408
439
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: t.textDim, fontStyle: "italic" }, children: "null" });
@@ -489,23 +520,72 @@ var JsonViewer = ({ data, theme }) => {
489
520
  scrollbarColor: `${t.scrollbarThumb} transparent`
490
521
  },
491
522
  children: [
492
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", marginBottom: "6px" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
493
- "button",
523
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
524
+ "div",
494
525
  {
495
- onClick: handleCopy,
496
526
  style: {
497
- backgroundColor: t.bgElevated,
498
- border: `1px solid ${t.border}`,
499
- color: t.text,
500
- padding: "3px 8px",
501
- borderRadius: "4px",
502
- fontSize: "11px",
503
- cursor: "pointer",
504
- transition: "background 0.15s ease"
527
+ display: "flex",
528
+ justifyContent: isRsc ? "space-between" : "flex-end",
529
+ alignItems: "center",
530
+ marginBottom: "8px"
505
531
  },
506
- children: copied ? "\u2713 Copied" : "Copy"
532
+ children: [
533
+ isRsc && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
534
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
535
+ "span",
536
+ {
537
+ style: {
538
+ backgroundColor: "rgba(56, 189, 248, 0.12)",
539
+ color: "#38bdf8",
540
+ border: "1px solid rgba(56, 189, 248, 0.28)",
541
+ padding: "2px 7px",
542
+ borderRadius: "4px",
543
+ fontSize: "11px",
544
+ fontWeight: 600,
545
+ display: "inline-flex",
546
+ alignItems: "center",
547
+ gap: "4px"
548
+ },
549
+ children: "\u26A1 Server Action Payload"
550
+ }
551
+ ),
552
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
553
+ "button",
554
+ {
555
+ onClick: () => setShowRawRsc((prev) => !prev),
556
+ style: {
557
+ background: "transparent",
558
+ border: "none",
559
+ color: t.textDim,
560
+ textDecoration: "underline",
561
+ fontSize: "11px",
562
+ cursor: "pointer",
563
+ padding: 0
564
+ },
565
+ children: showRawRsc ? "Show Decoded JSON" : "Show Raw Stream"
566
+ }
567
+ )
568
+ ] }),
569
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
570
+ "button",
571
+ {
572
+ onClick: handleCopy,
573
+ style: {
574
+ backgroundColor: t.bgElevated,
575
+ border: `1px solid ${t.border}`,
576
+ color: t.text,
577
+ padding: "3px 8px",
578
+ borderRadius: "4px",
579
+ fontSize: "11px",
580
+ cursor: "pointer",
581
+ transition: "background 0.15s ease"
582
+ },
583
+ children: copied ? "\u2713 Copied" : "Copy"
584
+ }
585
+ )
586
+ ]
507
587
  }
508
- ) }),
588
+ ),
509
589
  isJson ? renderValue(parsed) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
510
590
  "pre",
511
591
  {
package/dist/index.mjs CHANGED
@@ -355,25 +355,56 @@ import { useState } from "react";
355
355
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
356
356
  var JsonViewer = ({ data, theme }) => {
357
357
  const [copied, setCopied] = useState(false);
358
+ const [showRawRsc, setShowRawRsc] = useState(false);
358
359
  const t = tokens[theme];
359
- const handleCopy = () => {
360
- const text = typeof data === "string" ? data : JSON.stringify(data, null, 2);
361
- navigator.clipboard.writeText(text);
362
- setCopied(true);
363
- setTimeout(() => setCopied(false), 1500);
364
- };
365
360
  let parsed = data;
366
361
  let isJson = false;
362
+ let isRsc = false;
363
+ let rscData = null;
367
364
  if (typeof data === "string") {
368
365
  try {
369
366
  parsed = JSON.parse(data);
370
367
  isJson = true;
371
368
  } catch {
372
- isJson = false;
369
+ const lines = data.split("\n");
370
+ for (const line of lines) {
371
+ const colonIdx = line.indexOf(":");
372
+ if (colonIdx > 0 && colonIdx < 10) {
373
+ const prefix = line.substring(0, colonIdx).trim();
374
+ if (/^[0-9a-f]+$/i.test(prefix)) {
375
+ const body = line.substring(colonIdx + 1).trim();
376
+ if (body.startsWith("{") || body.startsWith("[")) {
377
+ try {
378
+ const candidate = JSON.parse(body);
379
+ if (candidate && typeof candidate === "object") {
380
+ if (typeof candidate.a === "string" && String(candidate.a).startsWith("$")) {
381
+ continue;
382
+ }
383
+ rscData = candidate;
384
+ isRsc = true;
385
+ }
386
+ } catch {
387
+ }
388
+ }
389
+ }
390
+ }
391
+ }
392
+ if (isRsc && !showRawRsc && rscData !== null) {
393
+ parsed = rscData;
394
+ isJson = true;
395
+ } else {
396
+ isJson = false;
397
+ }
373
398
  }
374
399
  } else if (data !== null && typeof data === "object") {
375
400
  isJson = true;
376
401
  }
402
+ const handleCopy = () => {
403
+ const text = isRsc && !showRawRsc && rscData !== null ? JSON.stringify(rscData, null, 2) : typeof data === "string" ? data : JSON.stringify(data, null, 2);
404
+ navigator.clipboard.writeText(text);
405
+ setCopied(true);
406
+ setTimeout(() => setCopied(false), 1500);
407
+ };
377
408
  const renderValue = (val, depth = 0) => {
378
409
  if (val === null) {
379
410
  return /* @__PURE__ */ jsx2("span", { style: { color: t.textDim, fontStyle: "italic" }, children: "null" });
@@ -460,23 +491,72 @@ var JsonViewer = ({ data, theme }) => {
460
491
  scrollbarColor: `${t.scrollbarThumb} transparent`
461
492
  },
462
493
  children: [
463
- /* @__PURE__ */ jsx2("div", { style: { display: "flex", justifyContent: "flex-end", marginBottom: "6px" }, children: /* @__PURE__ */ jsx2(
464
- "button",
494
+ /* @__PURE__ */ jsxs2(
495
+ "div",
465
496
  {
466
- onClick: handleCopy,
467
497
  style: {
468
- backgroundColor: t.bgElevated,
469
- border: `1px solid ${t.border}`,
470
- color: t.text,
471
- padding: "3px 8px",
472
- borderRadius: "4px",
473
- fontSize: "11px",
474
- cursor: "pointer",
475
- transition: "background 0.15s ease"
498
+ display: "flex",
499
+ justifyContent: isRsc ? "space-between" : "flex-end",
500
+ alignItems: "center",
501
+ marginBottom: "8px"
476
502
  },
477
- children: copied ? "\u2713 Copied" : "Copy"
503
+ children: [
504
+ isRsc && /* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
505
+ /* @__PURE__ */ jsx2(
506
+ "span",
507
+ {
508
+ style: {
509
+ backgroundColor: "rgba(56, 189, 248, 0.12)",
510
+ color: "#38bdf8",
511
+ border: "1px solid rgba(56, 189, 248, 0.28)",
512
+ padding: "2px 7px",
513
+ borderRadius: "4px",
514
+ fontSize: "11px",
515
+ fontWeight: 600,
516
+ display: "inline-flex",
517
+ alignItems: "center",
518
+ gap: "4px"
519
+ },
520
+ children: "\u26A1 Server Action Payload"
521
+ }
522
+ ),
523
+ /* @__PURE__ */ jsx2(
524
+ "button",
525
+ {
526
+ onClick: () => setShowRawRsc((prev) => !prev),
527
+ style: {
528
+ background: "transparent",
529
+ border: "none",
530
+ color: t.textDim,
531
+ textDecoration: "underline",
532
+ fontSize: "11px",
533
+ cursor: "pointer",
534
+ padding: 0
535
+ },
536
+ children: showRawRsc ? "Show Decoded JSON" : "Show Raw Stream"
537
+ }
538
+ )
539
+ ] }),
540
+ /* @__PURE__ */ jsx2(
541
+ "button",
542
+ {
543
+ onClick: handleCopy,
544
+ style: {
545
+ backgroundColor: t.bgElevated,
546
+ border: `1px solid ${t.border}`,
547
+ color: t.text,
548
+ padding: "3px 8px",
549
+ borderRadius: "4px",
550
+ fontSize: "11px",
551
+ cursor: "pointer",
552
+ transition: "background 0.15s ease"
553
+ },
554
+ children: copied ? "\u2713 Copied" : "Copy"
555
+ }
556
+ )
557
+ ]
478
558
  }
479
- ) }),
559
+ ),
480
560
  isJson ? renderValue(parsed) : /* @__PURE__ */ jsx2(
481
561
  "pre",
482
562
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexttrace/devtools",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Floating, dockable, resizable devtools overlay for NextTrace",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",