reqwise-core 1.1.5 → 1.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.
package/dist/index.mjs CHANGED
@@ -56,6 +56,18 @@ function initStorage(cfg3) {
56
56
  }
57
57
  function saveEntry(entry) {
58
58
  memory.push(entry);
59
+ if (config.historyTTL && config.historyTTL > 0) {
60
+ const now = Date.now();
61
+ const ttlMs = config.historyTTL * 24 * 60 * 60 * 1e3;
62
+ memory = memory.filter((e) => {
63
+ try {
64
+ const entryTime = new Date(e.timestamp).getTime();
65
+ return now - entryTime < ttlMs;
66
+ } catch (e2) {
67
+ return true;
68
+ }
69
+ });
70
+ }
59
71
  if (config.maxItems && memory.length > config.maxItems) {
60
72
  memory = memory.slice(-config.maxItems);
61
73
  }
@@ -242,13 +254,15 @@ var catalog = {
242
254
  form_url: "URL",
243
255
  form_headers: "Headers (JSON)",
244
256
  form_body: "Body (JSON)",
245
- send_request: "\u2192 Send Request",
257
+ send_request: "Send Request",
246
258
  clear_form: "Clear",
247
259
  enter_url_warning: "Please enter a URL",
248
260
  response_label: "Response",
249
261
  error_label: "Error",
250
262
  manual_badge: "Manual",
251
- time: "Time"
263
+ time: "Time",
264
+ all_methods: "All Methods",
265
+ all_statuses: "All Statuses"
252
266
  },
253
267
  tr: {
254
268
  requests: "\u0130stekler",
@@ -299,7 +313,9 @@ var catalog = {
299
313
  response_label: "Yan\u0131t",
300
314
  error_label: "Hata",
301
315
  manual_badge: "Manuel",
302
- time: "Saat"
316
+ time: "Saat",
317
+ all_methods: "T\xFCm Metotlar",
318
+ all_statuses: "T\xFCm Durumlar"
303
319
  },
304
320
  az: {
305
321
  requests: "Sor\u011Fular",
@@ -350,7 +366,9 @@ var catalog = {
350
366
  response_label: "Cavab",
351
367
  error_label: "X\u0259ta",
352
368
  manual_badge: "Manuel",
353
- time: "Vaxt"
369
+ time: "Vaxt",
370
+ all_methods: "B\xFCt\xFCn Metodlar",
371
+ all_statuses: "B\xFCt\xFCn Statuslar"
354
372
  },
355
373
  ru: {
356
374
  requests: "\u0417\u0430\u043F\u0440\u043E\u0441\u044B",
@@ -401,7 +419,9 @@ var catalog = {
401
419
  response_label: "\u041E\u0442\u0432\u0435\u0442",
402
420
  error_label: "\u041E\u0448\u0438\u0431\u043A\u0430",
403
421
  manual_badge: "\u0412\u0440\u0443\u0447\u043D\u0443\u044E",
404
- time: "\u0412\u0440\u0435\u043C\u044F"
422
+ time: "\u0412\u0440\u0435\u043C\u044F",
423
+ all_methods: "\u0412\u0441\u0435 \u043C\u0435\u0442\u043E\u0434\u044B",
424
+ all_statuses: "\u0412\u0441\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u044B"
405
425
  },
406
426
  de: {
407
427
  requests: "Anfragen",
@@ -452,7 +472,9 @@ var catalog = {
452
472
  response_label: "Antwort",
453
473
  error_label: "Fehler",
454
474
  manual_badge: "Manuell",
455
- time: "Zeit"
475
+ time: "Zeit",
476
+ all_methods: "Alle Methoden",
477
+ all_statuses: "Alle Status"
456
478
  },
457
479
  fr: {
458
480
  requests: "Requ\xEAtes",
@@ -503,7 +525,9 @@ var catalog = {
503
525
  response_label: "R\xE9ponse",
504
526
  error_label: "Erreur",
505
527
  manual_badge: "Manuel",
506
- time: "Heure"
528
+ time: "Heure",
529
+ all_methods: "Toutes les m\xE9thodes",
530
+ all_statuses: "Tous les statuts"
507
531
  },
508
532
  es: {
509
533
  requests: "Solicitudes",
@@ -554,7 +578,9 @@ var catalog = {
554
578
  response_label: "Respuesta",
555
579
  error_label: "Error",
556
580
  manual_badge: "Manual",
557
- time: "Hora"
581
+ time: "Hora",
582
+ all_methods: "Todos los m\xE9todos",
583
+ all_statuses: "Todos los estados"
558
584
  },
559
585
  pt: {
560
586
  requests: "Requisi\xE7\xF5es",
@@ -605,7 +631,9 @@ var catalog = {
605
631
  response_label: "Resposta",
606
632
  error_label: "Erro",
607
633
  manual_badge: "Manual",
608
- time: "Hora"
634
+ time: "Hora",
635
+ all_methods: "Todos os m\xE9todos",
636
+ all_statuses: "Todos os estados"
609
637
  },
610
638
  zh: {
611
639
  requests: "\u8BF7\u6C42",
@@ -656,7 +684,9 @@ var catalog = {
656
684
  response_label: "\u54CD\u5E94",
657
685
  error_label: "\u9519\u8BEF",
658
686
  manual_badge: "\u624B\u52A8",
659
- time: "\u65F6\u95F4"
687
+ time: "\u65F6\u95F4",
688
+ all_methods: "\u6240\u6709\u65B9\u6CD5",
689
+ all_statuses: "\u6240\u6709\u72B6\u6001"
660
690
  },
661
691
  ja: {
662
692
  requests: "\u30EA\u30AF\u30A8\u30B9\u30C8",
@@ -707,7 +737,9 @@ var catalog = {
707
737
  response_label: "\u30EC\u30B9\u30DD\u30F3\u30B9",
708
738
  error_label: "\u30A8\u30E9\u30FC",
709
739
  manual_badge: "\u624B\u52D5",
710
- time: "\u6642\u523B"
740
+ time: "\u6642\u523B",
741
+ all_methods: "\u3059\u3079\u3066\u306E\u30E1\u30BD\u30C3\u30C9",
742
+ all_statuses: "\u3059\u3079\u3066\u306E\u30B9\u30C6\u30FC\u30BF\u30B9"
711
743
  },
712
744
  ar: {
713
745
  requests: "\u0627\u0644\u0637\u0644\u0628\u0627\u062A",
@@ -758,7 +790,9 @@ var catalog = {
758
790
  response_label: "\u0627\u0644\u0627\u0633\u062A\u062C\u0627\u0628\u0629",
759
791
  error_label: "\u062E\u0637\u0623",
760
792
  manual_badge: "\u064A\u062F\u0648\u064A",
761
- time: "\u0627\u0644\u0648\u0642\u062A"
793
+ time: "\u0627\u0644\u0648\u0642\u062A",
794
+ all_methods: "\u062C\u0645\u064A\u0639 \u0627\u0644\u0623\u0633\u0627\u0644\u064A\u0628",
795
+ all_statuses: "\u062C\u0645\u064A\u0639 \u0627\u0644\u062D\u0627\u0644\u0627\u062A"
762
796
  },
763
797
  ko: {
764
798
  requests: "\uC694\uCCAD",
@@ -809,7 +843,9 @@ var catalog = {
809
843
  response_label: "\uC751\uB2F5",
810
844
  error_label: "\uC624\uB958",
811
845
  manual_badge: "\uC218\uB3D9",
812
- time: "\uC2DC\uAC04"
846
+ time: "\uC2DC\uAC04",
847
+ all_methods: "\uBAA8\uB4E0 \uBA54\uC11C\uB4DC",
848
+ all_statuses: "\uBAA8\uB4E0 \uC0C1\uD0DC"
813
849
  },
814
850
  it: {
815
851
  requests: "Richieste",
@@ -860,7 +896,9 @@ var catalog = {
860
896
  response_label: "Risposta",
861
897
  error_label: "Errore",
862
898
  manual_badge: "Manuale",
863
- time: "Ora"
899
+ time: "Ora",
900
+ all_methods: "Tutti i metodi",
901
+ all_statuses: "Tutti gli stati"
864
902
  },
865
903
  pl: {
866
904
  requests: "\u017B\u0105dania",
@@ -911,7 +949,9 @@ var catalog = {
911
949
  response_label: "Odpowied\u017A",
912
950
  error_label: "B\u0142\u0105d",
913
951
  manual_badge: "R\u0119cznie",
914
- time: "Czas"
952
+ time: "Czas",
953
+ all_methods: "Wszystkie metody",
954
+ all_statuses: "Wszystkie statusy"
915
955
  },
916
956
  nl: {
917
957
  requests: "Verzoeken",
@@ -962,7 +1002,9 @@ var catalog = {
962
1002
  response_label: "Antwoord",
963
1003
  error_label: "Fout",
964
1004
  manual_badge: "Handmatig",
965
- time: "Tijd"
1005
+ time: "Tijd",
1006
+ all_methods: "Alle methoden",
1007
+ all_statuses: "Alle statussen"
966
1008
  }
967
1009
  };
968
1010
  try {
@@ -1028,13 +1070,19 @@ var i18n_default = {
1028
1070
  init_storage();
1029
1071
  var START_TS = /* @__PURE__ */ Symbol("reqwise_start_ts");
1030
1072
  var cfg2 = {
1031
- theme: "dark",
1073
+ theme: "system",
1032
1074
  placement: "right",
1075
+ show: "general",
1033
1076
  defaultOpen: false,
1034
1077
  enabled: true,
1035
- maxItems: 200,
1078
+ hotkey: "ctrl+shift+e",
1079
+ maxItems: 500,
1036
1080
  persistHistory: true,
1037
- defaultLang: "en"
1081
+ defaultLang: "en",
1082
+ langs: ["en"],
1083
+ ignore: [],
1084
+ maskHeaders: [],
1085
+ maskFields: []
1038
1086
  };
1039
1087
  function initClient(c) {
1040
1088
  if (c) cfg2 = { ...cfg2 || {}, ...c };
@@ -1066,7 +1114,21 @@ function buildEntry(base) {
1066
1114
  }
1067
1115
  function recordPartial(entry) {
1068
1116
  const e = buildEntry(entry);
1117
+ try {
1118
+ if (cfg2.onRequest) cfg2.onRequest(entry);
1119
+ } catch (err) {
1120
+ console.error("[reqwise] onRequest callback error", err);
1121
+ }
1069
1122
  storage_default.saveEntry(e);
1123
+ try {
1124
+ if (e.error && cfg2.onError) {
1125
+ cfg2.onError(e);
1126
+ } else if (!e.error && cfg2.onResponse) {
1127
+ cfg2.onResponse(e);
1128
+ }
1129
+ } catch (err) {
1130
+ console.error("[reqwise] onResponse/onError callback error", err);
1131
+ }
1070
1132
  }
1071
1133
  function wrapAxios(instance) {
1072
1134
  if (!instance || typeof instance.interceptors !== "object") return;
@@ -1083,9 +1145,10 @@ function wrapAxios(instance) {
1083
1145
  const req = res.config || {};
1084
1146
  const start = req[START_TS] || Date.now();
1085
1147
  const duration = Date.now() - start;
1148
+ const fullUrl = (req.baseURL || "") + (req.url || "");
1086
1149
  const entry = buildEntry({
1087
1150
  method: (req.method || "GET").toUpperCase(),
1088
- url: req.url || req.baseURL || "",
1151
+ url: fullUrl || "",
1089
1152
  requestHeaders: filter_default.maskHeaders(req.headers),
1090
1153
  requestBody: filter_default.maskFields(req.data),
1091
1154
  status: res.status,
@@ -1105,9 +1168,10 @@ function wrapAxios(instance) {
1105
1168
  const start = req[START_TS] || Date.now();
1106
1169
  const duration = Date.now() - start;
1107
1170
  const response = err?.response || {};
1171
+ const fullUrl = (req.baseURL || "") + (req.url || "");
1108
1172
  const entry = buildEntry({
1109
1173
  method: (req.method || "GET").toUpperCase(),
1110
- url: req.url || req.baseURL || "",
1174
+ url: fullUrl || "",
1111
1175
  requestHeaders: filter_default.maskHeaders(req.headers),
1112
1176
  requestBody: filter_default.maskFields(req.data),
1113
1177
  status: response.status,
@@ -1167,50 +1231,50 @@ async function fetchWithRecord(input, init) {
1167
1231
  throw err;
1168
1232
  }
1169
1233
  }
1170
- async function get(url, config2) {
1234
+ async function get(url, config3) {
1171
1235
  if (cfg2.axiosInstance && typeof cfg2.axiosInstance.get === "function") {
1172
- return cfg2.axiosInstance.get(url, config2);
1236
+ return cfg2.axiosInstance.get(url, config3);
1173
1237
  }
1174
- return fetchWithRecord(url, { method: "GET", headers: config2?.headers });
1238
+ return fetchWithRecord(url, { method: "GET", headers: config3?.headers });
1175
1239
  }
1176
- async function post(url, data, config2) {
1240
+ async function post(url, data, config3) {
1177
1241
  if (cfg2.axiosInstance && typeof cfg2.axiosInstance.post === "function") {
1178
- return cfg2.axiosInstance.post(url, data, config2);
1242
+ return cfg2.axiosInstance.post(url, data, config3);
1179
1243
  }
1180
1244
  const body = typeof data === "string" ? data : JSON.stringify(data);
1181
1245
  return fetchWithRecord(url, {
1182
1246
  method: "POST",
1183
1247
  body,
1184
- headers: { "Content-Type": "application/json", ...config2?.headers }
1248
+ headers: { "Content-Type": "application/json", ...config3?.headers }
1185
1249
  });
1186
1250
  }
1187
- async function put(url, data, config2) {
1251
+ async function put(url, data, config3) {
1188
1252
  if (cfg2.axiosInstance && typeof cfg2.axiosInstance.put === "function") {
1189
- return cfg2.axiosInstance.put(url, data, config2);
1253
+ return cfg2.axiosInstance.put(url, data, config3);
1190
1254
  }
1191
1255
  const body = typeof data === "string" ? data : JSON.stringify(data);
1192
1256
  return fetchWithRecord(url, {
1193
1257
  method: "PUT",
1194
1258
  body,
1195
- headers: { "Content-Type": "application/json", ...config2?.headers }
1259
+ headers: { "Content-Type": "application/json", ...config3?.headers }
1196
1260
  });
1197
1261
  }
1198
- async function patch(url, data, config2) {
1262
+ async function patch(url, data, config3) {
1199
1263
  if (cfg2.axiosInstance && typeof cfg2.axiosInstance.patch === "function") {
1200
- return cfg2.axiosInstance.patch(url, data, config2);
1264
+ return cfg2.axiosInstance.patch(url, data, config3);
1201
1265
  }
1202
1266
  const body = typeof data === "string" ? data : JSON.stringify(data);
1203
1267
  return fetchWithRecord(url, {
1204
1268
  method: "PATCH",
1205
1269
  body,
1206
- headers: { "Content-Type": "application/json", ...config2?.headers }
1270
+ headers: { "Content-Type": "application/json", ...config3?.headers }
1207
1271
  });
1208
1272
  }
1209
- async function del(url, config2) {
1273
+ async function del(url, config3) {
1210
1274
  if (cfg2.axiosInstance && typeof cfg2.axiosInstance.delete === "function") {
1211
- return cfg2.axiosInstance.delete(url, config2);
1275
+ return cfg2.axiosInstance.delete(url, config3);
1212
1276
  }
1213
- return fetchWithRecord(url, { method: "DELETE", headers: config2?.headers });
1277
+ return fetchWithRecord(url, { method: "DELETE", headers: config3?.headers });
1214
1278
  }
1215
1279
  var ReqwiseClient = {
1216
1280
  init: initClient,
@@ -1251,7 +1315,8 @@ var styles = `
1251
1315
  position: fixed;
1252
1316
  right: 0;
1253
1317
  top: 0;
1254
- height: auto;
1318
+ bottom: 0;
1319
+ height: 100vh;
1255
1320
  width: var(--rq-width);
1256
1321
  min-width: var(--rq-min-width);
1257
1322
  max-width: 800px;
@@ -1264,7 +1329,6 @@ var styles = `
1264
1329
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif;
1265
1330
  font-size: 14px;
1266
1331
  line-height: 1.5;
1267
- overflow: visible;
1268
1332
  transition: transform var(--rq-duration) ease;
1269
1333
  }
1270
1334
 
@@ -1373,6 +1437,7 @@ var styles = `
1373
1437
  display: flex;
1374
1438
  gap: 32px;
1375
1439
  padding: 0 24px;
1440
+ margin-bottom: 16px;
1376
1441
  border-bottom: 1px solid var(--rq-border);
1377
1442
  flex-shrink: 0;
1378
1443
  background: var(--rq-bg);
@@ -1402,11 +1467,12 @@ var styles = `
1402
1467
 
1403
1468
  /* Body/Content */
1404
1469
  #reqwise-panel .rq-body {
1405
- overflow-y: auto;
1406
- overflow-x: hidden;
1407
- padding: 24px;
1470
+ display: flex;
1471
+ flex-direction: column;
1472
+ overflow: hidden;
1473
+ padding: 0;
1408
1474
  flex: 1 1 auto;
1409
- scroll-behavior: smooth;
1475
+ min-height: 0;
1410
1476
  }
1411
1477
 
1412
1478
  #reqwise-panel .rq-body::-webkit-scrollbar {
@@ -1585,6 +1651,37 @@ var styles = `
1585
1651
  color: var(--rq-fg);
1586
1652
  }
1587
1653
 
1654
+ /* Expandable JSON - collapsed by default */
1655
+ .rq-json-expandable {
1656
+ transition: max-height var(--rq-duration) ease;
1657
+ overflow: hidden;
1658
+ }
1659
+
1660
+ .rq-json-expandable.rq-json-collapsed {
1661
+ max-height: 140px;
1662
+ position: relative;
1663
+ overflow-y: hidden;
1664
+ }
1665
+
1666
+ .rq-json-expandable.rq-json-collapsed::after {
1667
+ content: '';
1668
+ position: absolute;
1669
+ bottom: 0;
1670
+ left: 0;
1671
+ right: 0;
1672
+ height: 40px;
1673
+ background: linear-gradient(transparent, var(--rq-bg-secondary));
1674
+ pointer-events: none;
1675
+ }
1676
+
1677
+ .rq-json-expandable:not(.rq-json-collapsed) {
1678
+ max-height: none;
1679
+ }
1680
+
1681
+ .rq-json-expandable:not(.rq-json-collapsed)::after {
1682
+ display: none;
1683
+ }
1684
+
1588
1685
  .rq-json-key {
1589
1686
  color: #0ea5e9;
1590
1687
  }
@@ -1747,6 +1844,25 @@ var styles = `
1747
1844
  opacity: 0.9;
1748
1845
  }
1749
1846
 
1847
+ /* Expand/collapse toggle */
1848
+ .rq-expand-toggle {
1849
+ padding: 4px 8px;
1850
+ font-size: 11px;
1851
+ background: var(--rq-bg-secondary);
1852
+ border: 1px solid var(--rq-border);
1853
+ border-radius: 3px;
1854
+ color: var(--rq-fg);
1855
+ cursor: pointer;
1856
+ font-weight: 500;
1857
+ transition: all var(--rq-duration) ease;
1858
+ white-space: nowrap;
1859
+ }
1860
+
1861
+ .rq-expand-toggle:hover {
1862
+ border-color: var(--rq-fg-secondary);
1863
+ background: rgba(255, 255, 255, 0.08);
1864
+ }
1865
+
1750
1866
  /* Placements */
1751
1867
  #reqwise-panel.placement-left {
1752
1868
  left: 0;
@@ -1819,63 +1935,84 @@ var styles = `
1819
1935
  display: inline-flex !important;
1820
1936
  }
1821
1937
 
1822
- .rq-toggle:hover { transform: scale(1.03); }
1823
-
1824
1938
  .rq-toggle img { width: 20px; height: 20px; object-fit: contain; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.08)); }
1825
1939
 
1826
- /* Placement-specific toggle positioning (relative to panel so it moves with it) */
1827
- #reqwise-panel.placement-right .rq-toggle {
1940
+ /* Toggle button positioning (inside panel, at the edge) */
1941
+ .rq-toggle {
1828
1942
  position: absolute;
1829
- left: -40px; /* adjacent to panel, to the left */
1830
1943
  top: 50%;
1831
1944
  transform: translateY(-50%);
1945
+ z-index: calc(var(--rq-z) + 1);
1946
+ }
1947
+
1948
+ #reqwise-panel.placement-right .rq-toggle {
1949
+ left: -40px;
1832
1950
  border-radius: 6px 0 0 6px;
1833
- writing-mode: vertical-rl; /* vertical text, reading from right side */
1951
+ writing-mode: vertical-rl;
1834
1952
  width: 40px;
1835
1953
  }
1836
1954
 
1837
1955
  #reqwise-panel.placement-left .rq-toggle {
1838
- position: absolute;
1839
- right: -40px; /* adjacent to panel, to the right (panel on left) */
1840
- top: 50%;
1841
- transform: translateY(-50%);
1956
+ right: -40px;
1842
1957
  border-radius: 0 6px 6px 0;
1843
- writing-mode: vertical-rl; /* match right placement so text faces inward */
1958
+ writing-mode: vertical-rl;
1844
1959
  width: 40px;
1845
1960
  }
1846
1961
 
1847
- /* Rotate logo when toggle is vertical so it faces toward the page (opposite of panel) */
1848
1962
  #reqwise-panel.placement-right .rq-toggle img { transform: rotate(90deg); }
1849
1963
  #reqwise-panel.placement-left .rq-toggle img { transform: rotate(-90deg); }
1850
1964
 
1851
1965
  #reqwise-panel.placement-top .rq-toggle {
1852
- position: absolute;
1853
- bottom: -40px; /* place toggle below the top panel (under it) */
1966
+ top: 100%;
1854
1967
  left: 50%;
1855
1968
  transform: translateX(-50%);
1856
- writing-mode: horizontal-tb;
1857
1969
  border-radius: 0 0 6px 6px;
1970
+ writing-mode: horizontal-tb;
1858
1971
  width: auto;
1859
1972
  min-width: 140px;
1860
- padding: 8px 16px;
1973
+ padding: 8px 12px;
1974
+ }
1975
+
1976
+ #reqwise-panel.placement-top[data-size="full"] .rq-toggle {
1977
+ top: auto;
1978
+ bottom: 0;
1979
+ }
1980
+
1981
+ #reqwise-panel.placement-top.rq-closed[data-size="full"] .rq-toggle {
1982
+ top: 100%;
1983
+ bottom: auto;
1861
1984
  }
1862
1985
 
1863
1986
  #reqwise-panel.placement-bottom .rq-toggle {
1864
- position: absolute;
1865
- top: -40px; /* place toggle above the bottom panel (on top of it) */
1987
+ bottom: 100%;
1988
+ top: auto;
1866
1989
  left: 50%;
1867
1990
  transform: translateX(-50%);
1868
- writing-mode: horizontal-tb;
1869
1991
  border-radius: 6px 6px 0 0;
1992
+ writing-mode: horizontal-tb;
1870
1993
  width: auto;
1871
1994
  min-width: 140px;
1872
- padding: 8px 16px;
1995
+ padding: 8px 12px;
1996
+ }
1997
+
1998
+ #reqwise-panel.placement-bottom[data-size="full"] .rq-toggle {
1999
+ bottom: auto;
2000
+ top: 0;
2001
+ }
2002
+
2003
+ #reqwise-panel.placement-bottom.rq-closed[data-size="full"] .rq-toggle {
2004
+ bottom: 100%;
2005
+ top: auto;
1873
2006
  }
1874
2007
 
1875
2008
  .rq-toggle span { white-space: nowrap; }
1876
2009
 
1877
2010
  /* Scale wrapper: transforms content inside aside without affecting panel slide transform */
1878
2011
  .rq-scale-wrapper {
2012
+ display: flex;
2013
+ flex-direction: column;
2014
+ min-height: 0;
2015
+ flex: 1;
1879
2016
  transform-origin: center center;
1880
2017
  transition: transform var(--rq-duration) ease;
1881
2018
  }
@@ -1885,12 +2022,27 @@ var styles = `
1885
2022
  .rq-zoom-btn { background: transparent; border: 1px solid var(--rq-border); color: var(--rq-fg); padding: 6px 8px; border-radius: 6px; cursor: pointer; font-weight: 700 }
1886
2023
  .rq-zoom-btn:hover { background: rgba(255,255,255,0.02) }
1887
2024
 
1888
- /* Panel closed states: slide fully off-screen toward its placement */
2025
+ /* Panel closed states: button stays at screen edge */
1889
2026
  #reqwise-panel.placement-right.rq-closed { transform: translateX(100%); }
1890
2027
  #reqwise-panel.placement-left.rq-closed { transform: translateX(-100%); }
1891
2028
  #reqwise-panel.placement-top.rq-closed { transform: translateY(-100%); }
1892
2029
  #reqwise-panel.placement-bottom.rq-closed { transform: translateY(100%); }
1893
2030
 
2031
+ /* Size variants: sm, md, lg, full */
2032
+ #reqwise-panel[data-size="sm"] { width: 320px; }
2033
+ #reqwise-panel[data-size="md"] { width: 420px; }
2034
+ #reqwise-panel[data-size="lg"] { width: 560px; }
2035
+ #reqwise-panel[data-size="full"] { width: 100vw; max-width: 100vw; }
2036
+
2037
+ #reqwise-panel.placement-top[data-size="sm"],
2038
+ #reqwise-panel.placement-bottom[data-size="sm"] { width: 100vw; height: 30vh; }
2039
+ #reqwise-panel.placement-top[data-size="md"],
2040
+ #reqwise-panel.placement-bottom[data-size="md"] { width: 100vw; height: 40vh; }
2041
+ #reqwise-panel.placement-top[data-size="lg"],
2042
+ #reqwise-panel.placement-bottom[data-size="lg"] { width: 100vw; height: 55vh; }
2043
+ #reqwise-panel.placement-top[data-size="full"],
2044
+ #reqwise-panel.placement-bottom[data-size="full"] { width: 100vw; height: 100vh; }
2045
+
1894
2046
  /* Corner handles for resize cursor (invisible) */
1895
2047
  .rq-corner-handle {
1896
2048
  position: absolute;
@@ -1904,6 +2056,17 @@ var styles = `
1904
2056
  .rq-corner-bottom-left { left: -8px; bottom: -8px; cursor: nesw-resize; }
1905
2057
  .rq-corner-bottom-right { right: -8px; bottom: -8px; cursor: nwse-resize; }
1906
2058
 
2059
+ /* Highlight variants: error and slow */
2060
+ .rq-card.rq-highlight-error {
2061
+ border-left: 4px solid #ef4444;
2062
+ background: rgba(239, 68, 68, 0.04);
2063
+ }
2064
+
2065
+ .rq-card.rq-highlight-slow {
2066
+ border-left: 4px solid #f97316;
2067
+ background: rgba(249, 115, 22, 0.04);
2068
+ }
2069
+
1907
2070
  /* Responsive */
1908
2071
  @media (max-width: 768px) {
1909
2072
  :root {
@@ -1951,6 +2114,175 @@ var styles = `
1951
2114
  scroll-behavior: auto !important;
1952
2115
  }
1953
2116
  }
2117
+
2118
+ /* Highlight styles for error and slow requests */
2119
+ #reqwise-panel .rq-card.rq-error {
2120
+ border: 2px solid var(--rq-error) !important;
2121
+ background: rgba(239, 68, 68, 0.03);
2122
+ }
2123
+
2124
+ #reqwise-panel .rq-card.rq-slow {
2125
+ border: 2px solid var(--rq-warning) !important;
2126
+ background: rgba(249, 115, 22, 0.03);
2127
+ }
2128
+
2129
+ /* Font sizing consistency */
2130
+ #reqwise-panel {
2131
+ font-size: 14px;
2132
+ }
2133
+
2134
+ #reqwise-panel .rq-card-title {
2135
+ font-size: 14px;
2136
+ font-weight: 600;
2137
+ margin: 0;
2138
+ white-space: nowrap;
2139
+ overflow: hidden;
2140
+ text-overflow: ellipsis;
2141
+ }
2142
+
2143
+ #reqwise-panel .rq-card-header {
2144
+ display: flex;
2145
+ align-items: center;
2146
+ gap: 8px;
2147
+ flex-wrap: wrap;
2148
+ }
2149
+
2150
+ #reqwise-panel .rq-meta-item {
2151
+ display: flex;
2152
+ flex-direction: column;
2153
+ gap: 4px;
2154
+ font-size: 13px;
2155
+ }
2156
+
2157
+ #reqwise-panel .rq-meta-label {
2158
+ font-size: 12px;
2159
+ font-weight: 600;
2160
+ color: var(--rq-fg-secondary);
2161
+ }
2162
+
2163
+ #reqwise-panel .rq-meta-code {
2164
+ font-size: 12px;
2165
+ font-family: 'Monaco', 'Courier New', monospace;
2166
+ word-break: break-all;
2167
+ }
2168
+
2169
+ /* Main content container */
2170
+ #reqwise-panel .rq-main {
2171
+ min-height: 0;
2172
+ flex: 1;
2173
+ overflow-y: auto;
2174
+ overflow-x: hidden;
2175
+ padding: 24px;
2176
+ scroll-behavior: smooth;
2177
+ }
2178
+
2179
+ #reqwise-panel .rq-main::-webkit-scrollbar {
2180
+ width: 8px;
2181
+ }
2182
+
2183
+ #reqwise-panel .rq-main::-webkit-scrollbar-track {
2184
+ background: transparent;
2185
+ }
2186
+
2187
+ #reqwise-panel .rq-main::-webkit-scrollbar-thumb {
2188
+ background: var(--rq-border);
2189
+ border-radius: 4px;
2190
+ }
2191
+
2192
+ #reqwise-panel .rq-main::-webkit-scrollbar-thumb:hover {
2193
+ background: var(--rq-fg-secondary);
2194
+ }
2195
+
2196
+ /* Scroll in lists */
2197
+ #reqwise-panel .rq-list {
2198
+ overflow-y: auto;
2199
+ overflow-x: hidden;
2200
+ }
2201
+
2202
+ #reqwise-panel .rq-list::-webkit-scrollbar {
2203
+ width: 8px;
2204
+ }
2205
+
2206
+ #reqwise-panel .rq-list::-webkit-scrollbar-track {
2207
+ background: transparent;
2208
+ }
2209
+
2210
+ #reqwise-panel .rq-list::-webkit-scrollbar-thumb {
2211
+ background: var(--rq-border);
2212
+ border-radius: 4px;
2213
+ }
2214
+
2215
+ #reqwise-panel .rq-list::-webkit-scrollbar-thumb:hover {
2216
+ background: var(--rq-fg-secondary);
2217
+ }
2218
+
2219
+ /* Zoom buttons fix */
2220
+ #reqwise-panel .rq-zoom-btn {
2221
+ min-width: 32px;
2222
+ height: 32px;
2223
+ padding: 6px;
2224
+ display: flex;
2225
+ align-items: center;
2226
+ justify-content: center;
2227
+ background: var(--rq-bg-secondary);
2228
+ border: 1px solid var(--rq-border);
2229
+ color: var(--rq-fg);
2230
+ border-radius: 6px;
2231
+ cursor: pointer;
2232
+ font-weight: 700;
2233
+ font-size: 14px;
2234
+ transition: background 150ms ease;
2235
+ }
2236
+
2237
+ #reqwise-panel .rq-zoom-btn:hover {
2238
+ background: rgba(255, 255, 255, 0.08);
2239
+ }
2240
+
2241
+ #reqwise-panel .rq-zoom-btn:active {
2242
+ background: rgba(255, 255, 255, 0.12);
2243
+ }
2244
+
2245
+ /* Group styles */
2246
+ #reqwise-panel .rq-group {
2247
+ margin-bottom: 16px;
2248
+ }
2249
+
2250
+ #reqwise-panel .rq-group-header {
2251
+ padding: 12px 24px;
2252
+ background: var(--rq-bg-secondary);
2253
+ border: 1px solid var(--rq-border);
2254
+ border-radius: 6px;
2255
+ font-weight: 600;
2256
+ font-size: 13px;
2257
+ cursor: pointer;
2258
+ user-select: none;
2259
+ display: flex;
2260
+ align-items: center;
2261
+ justify-content: space-between;
2262
+ gap: 8px;
2263
+ }
2264
+
2265
+ #reqwise-panel .rq-group-header:hover {
2266
+ background: rgba(255, 255, 255, 0.05);
2267
+ }
2268
+
2269
+ #reqwise-panel .rq-group-items {
2270
+ margin-top: 8px;
2271
+ padding-left: 12px;
2272
+ }
2273
+
2274
+ #reqwise-panel .rq-group-items.collapsed {
2275
+ display: none;
2276
+ }
2277
+
2278
+ #reqwise-panel .rq-group-toggle {
2279
+ display: inline-block;
2280
+ transition: transform var(--rq-duration) ease;
2281
+ }
2282
+
2283
+ #reqwise-panel .rq-group-toggle.collapsed {
2284
+ transform: rotate(-90deg);
2285
+ }
1954
2286
  `;
1955
2287
  var styles_default = styles;
1956
2288
 
@@ -2271,15 +2603,30 @@ var panel = /* @__PURE__ */ (() => {
2271
2603
  else if (cfg3.theme === "dark") p.setAttribute("data-theme", "dark");
2272
2604
  else p.removeAttribute("data-theme");
2273
2605
  }
2274
- function mount(config2) {
2606
+ function applySize() {
2607
+ if (!isBrowser()) return;
2608
+ const p = document.getElementById(PANEL_ID);
2609
+ if (!p) return;
2610
+ p.setAttribute("data-size", cfg3.size || "md");
2611
+ }
2612
+ function applyOpacity() {
2613
+ if (!isBrowser()) return;
2614
+ const p = document.getElementById(PANEL_ID);
2615
+ if (!p) return;
2616
+ const opacity = cfg3.opacity ?? 1;
2617
+ p.style.opacity = String(Math.max(0, Math.min(1, opacity)));
2618
+ }
2619
+ function mount(config3) {
2275
2620
  try {
2276
2621
  if (!isBrowser()) return;
2277
2622
  if (mounted) return;
2278
- cfg3 = { defaultOpen: false, placement: "right", hotkey: "ctrl+shift+e", theme: "system", ...config2 || {} };
2623
+ cfg3 = { defaultOpen: false, placement: "right", hotkey: "ctrl+shift+e", theme: "system", size: "md", opacity: 1, ...config3 || {} };
2279
2624
  hotkeyParts = parseHotkey(cfg3.hotkey);
2280
2625
  injectStyles();
2281
2626
  createPanelElement();
2282
2627
  applyTheme();
2628
+ applySize();
2629
+ applyOpacity();
2283
2630
  createToggle();
2284
2631
  try {
2285
2632
  const p = document.getElementById(PANEL_ID);
@@ -2316,22 +2663,11 @@ var panel = /* @__PURE__ */ (() => {
2316
2663
  function setOpenState(next) {
2317
2664
  try {
2318
2665
  const p = document.getElementById(PANEL_ID);
2319
- const t2 = document.getElementById(TOGGLE_ID);
2320
2666
  open = !!next;
2321
2667
  if (p) {
2322
2668
  p.classList.toggle("rq-closed", !open);
2323
2669
  p.setAttribute("aria-hidden", String(!open));
2324
2670
  }
2325
- if (open && renderer2 && p) {
2326
- const body = p.querySelector(".rq-body");
2327
- if (body) {
2328
- try {
2329
- renderer2(body);
2330
- } catch (e) {
2331
- console.error("[reqwise] renderer error", e);
2332
- }
2333
- }
2334
- }
2335
2671
  } catch (e) {
2336
2672
  console.error("[reqwise] setOpenState error", e);
2337
2673
  }
@@ -2393,6 +2729,10 @@ var panel_default = panel;
2393
2729
  // src/renderer.ts
2394
2730
  init_storage();
2395
2731
  var ENDPOINTS_KEY = "reqwise_endpoints_v1";
2732
+ var config2 = { show: "general" };
2733
+ function setConfig2(cfg3) {
2734
+ config2 = { ...config2, ...cfg3 };
2735
+ }
2396
2736
  function safeParseJSON(s) {
2397
2737
  try {
2398
2738
  return s ? JSON.parse(s) : null;
@@ -2425,10 +2765,10 @@ function inferType(val) {
2425
2765
  function updateEndpointsFromEntry(entry) {
2426
2766
  try {
2427
2767
  if (!entry || !entry.url) return;
2428
- const { pathname, search } = normalizePath(entry.url);
2768
+ const { pathname, search, origin } = normalizePath(entry.url);
2429
2769
  const endpoints = loadEndpoints();
2430
2770
  const key = pathname;
2431
- if (!endpoints[key]) endpoints[key] = { path: key, methods: {}, params: {}, examples: [], count: 0, lastSeen: 0 };
2771
+ if (!endpoints[key]) endpoints[key] = { path: pathname, fullPath: entry.url.split("?")[0], origin, methods: {}, params: {}, examples: [], count: 0, lastSeen: 0 };
2432
2772
  const meta = endpoints[key];
2433
2773
  meta.count = (meta.count || 0) + 1;
2434
2774
  meta.lastSeen = Date.now();
@@ -2500,6 +2840,63 @@ function renderCurrent(container) {
2500
2840
  }
2501
2841
  const html = entries.map((e) => formatCard(e)).join("");
2502
2842
  main.innerHTML = html;
2843
+ const sendBtns = main.querySelectorAll(".rq-send-btn");
2844
+ sendBtns.forEach((btn) => {
2845
+ btn.addEventListener("click", () => {
2846
+ const method = btn.getAttribute("data-method") || "GET";
2847
+ const url = btn.getAttribute("data-url") || "";
2848
+ const bodyStr = btn.getAttribute("data-body") || "{}";
2849
+ let body = {};
2850
+ try {
2851
+ body = JSON.parse(bodyStr);
2852
+ } catch (e) {
2853
+ }
2854
+ const panel2 = document.getElementById("reqwise-panel");
2855
+ if (!panel2) return;
2856
+ const sendTab = panel2.querySelector('[data-tabname="send"]');
2857
+ if (sendTab) sendTab.click();
2858
+ setTimeout(() => {
2859
+ const form = main.querySelector(".rq-form");
2860
+ if (!form) return;
2861
+ const methodSelect = form.querySelector('[name="method"]');
2862
+ const urlInput = form.querySelector('[name="url"]');
2863
+ const bodyInput = form.querySelector('[name="body"]');
2864
+ if (methodSelect) methodSelect.value = method;
2865
+ if (urlInput) {
2866
+ urlInput.value = url;
2867
+ urlInput.focus();
2868
+ }
2869
+ if (bodyInput && Object.keys(body).length > 0) {
2870
+ bodyInput.value = JSON.stringify(body, null, 2);
2871
+ }
2872
+ }, 50);
2873
+ });
2874
+ });
2875
+ const expandToggles = main.querySelectorAll(".rq-expand-toggle");
2876
+ expandToggles.forEach((btn) => {
2877
+ btn.addEventListener("click", () => {
2878
+ const entryId = btn.getAttribute("data-entry-id");
2879
+ if (!entryId) return;
2880
+ const expandables = main.querySelectorAll(`.rq-json-expandable[data-entry-id="${entryId}"]`);
2881
+ const allExpanded = Array.from(expandables).every((el) => !el.classList.contains("rq-json-collapsed"));
2882
+ expandables.forEach((el) => {
2883
+ if (allExpanded) {
2884
+ el.classList.add("rq-json-collapsed");
2885
+ } else {
2886
+ el.classList.remove("rq-json-collapsed");
2887
+ }
2888
+ });
2889
+ btn.textContent = allExpanded ? "Show more \u25BC" : "Show less \u25B2";
2890
+ });
2891
+ });
2892
+ }
2893
+ function countJSONLines(obj) {
2894
+ try {
2895
+ const json = typeof obj === "string" ? obj : JSON.stringify(obj, null, 2);
2896
+ return json.split("\n").length;
2897
+ } catch (e) {
2898
+ return 0;
2899
+ }
2503
2900
  }
2504
2901
  function formatCard(e) {
2505
2902
  const statusBadge = getStatusBadge(e.status);
@@ -2507,6 +2904,34 @@ function formatCard(e) {
2507
2904
  const errorClass = e.error ? "error" : "";
2508
2905
  const duration = e.duration ? `${e.duration}ms` : "\u2014";
2509
2906
  const statusText = e.statusText ? e.statusText : "";
2907
+ const entryId = e.id || "";
2908
+ const requestLines = e.requestBody ? countJSONLines(e.requestBody) : 0;
2909
+ const responseLines = e.responseBody ? countJSONLines(e.responseBody) : 0;
2910
+ const hasLargeContent = requestLines > 10 || responseLines > 10;
2911
+ if (config2.show === "general") {
2912
+ return `
2913
+ <div class="rq-card">
2914
+ <div class="rq-card-header">
2915
+ <h3 class="rq-card-title">${e.method || "GET"} ${extractPath(e.url)}</h3>
2916
+ ${e.source === "manual" ? '<span class="rq-badge">' + i18n_default.t("manual_badge") + "</span>" : ""}
2917
+ ${statusBadge}
2918
+ </div>
2919
+ <div class="rq-meta">
2920
+ <div class="rq-meta-item">
2921
+ <span class="rq-meta-label">${i18n_default.t("duration")}:</span>
2922
+ <code class="rq-meta-code">${duration}</code>
2923
+ </div>
2924
+ <div class="rq-meta-item">
2925
+ <span class="rq-meta-label">${i18n_default.t("time")}:</span>
2926
+ <code class="rq-meta-code">${new Date(e.timestamp).toLocaleTimeString()}</code>
2927
+ </div>
2928
+ </div>
2929
+ <div style="margin-top: 12px; display: flex; gap: 8px;">
2930
+ <button class="rq-btn primary rq-send-btn" data-entry-id="${entryId}" data-method="${escapeHtml(e.method || "GET")}" data-url="${escapeHtml(e.url)}" data-body="${escapeHtml(JSON.stringify(e.requestBody || {}))}" style="font-size: 12px; padding: 6px 12px; flex: 1;">\u2192 ${i18n_default.t("send_request")}</button>
2931
+ </div>
2932
+ </div>
2933
+ `;
2934
+ }
2510
2935
  return `
2511
2936
  <div class="rq-card">
2512
2937
  <div class="rq-card-header">
@@ -2514,7 +2939,7 @@ function formatCard(e) {
2514
2939
  ${e.source === "manual" ? '<span class="rq-badge">' + i18n_default.t("manual_badge") + "</span>" : ""}
2515
2940
  ${statusBadge}
2516
2941
  </div>
2517
-
2942
+
2518
2943
  <div class="rq-meta">
2519
2944
  <div class="rq-meta-item">
2520
2945
  <span class="rq-meta-label">${i18n_default.t("form_url")}:</span>
@@ -2538,8 +2963,11 @@ function formatCard(e) {
2538
2963
 
2539
2964
  ${e.requestBody && ["POST", "PUT", "PATCH"].includes(e.method || "") ? `
2540
2965
  <div class="rq-section">
2541
- <div class="rq-section-label">${i18n_default.t("request")} ${i18n_default.t("body")}</div>
2542
- <div class="rq-json">${highlightJSON(e.requestBody)}</div>
2966
+ <div class="rq-section-label">
2967
+ ${i18n_default.t("request")} ${i18n_default.t("body")}
2968
+ ${requestLines > 10 ? `<button class="rq-expand-toggle" data-entry-id="${entryId}" style="margin-left: 8px;">Show more \u25BC</button>` : ""}
2969
+ </div>
2970
+ <div class="rq-json ${requestLines > 10 ? "rq-json-expandable rq-json-collapsed" : ""}" data-entry-id="${entryId}" data-section="request">${highlightJSON(e.requestBody)}</div>
2543
2971
  </div>
2544
2972
  ` : ""}
2545
2973
 
@@ -2555,10 +2983,17 @@ function formatCard(e) {
2555
2983
 
2556
2984
  ${e.responseBody !== void 0 ? `
2557
2985
  <div class="rq-section">
2558
- <div class="rq-section-label">${i18n_default.t("response_label")}</div>
2559
- <div class="rq-json">${highlightJSON(e.responseBody)}</div>
2986
+ <div class="rq-section-label">
2987
+ ${i18n_default.t("response_label")}
2988
+ ${responseLines > 10 ? `<button class="rq-expand-toggle" data-entry-id="${entryId}" style="margin-left: 8px;">Show more \u25BC</button>` : ""}
2989
+ </div>
2990
+ <div class="rq-json ${responseLines > 10 ? "rq-json-expandable rq-json-collapsed" : ""}" data-entry-id="${entryId}" data-section="response">${highlightJSON(e.responseBody)}</div>
2560
2991
  </div>
2561
2992
  ` : ""}
2993
+
2994
+ <div style="margin-top: 12px; display: flex; gap: 8px;">
2995
+ <button class="rq-btn primary rq-send-btn" data-entry-id="${entryId}" data-method="${escapeHtml(e.method || "GET")}" data-url="${escapeHtml(e.url)}" data-body="${escapeHtml(JSON.stringify(e.requestBody || {}))}" style="font-size: 12px; padding: 6px 12px; flex: 1;">\u2192 ${i18n_default.t("send_request")}</button>
2996
+ </div>
2562
2997
  </div>
2563
2998
  `;
2564
2999
  }
@@ -2640,8 +3075,24 @@ function renderHistory(container) {
2640
3075
  return;
2641
3076
  }
2642
3077
  main.innerHTML = `
2643
- <div class="rq-section" style="margin-bottom: 16px;">
2644
- <input type="text" class="rq-filter rq-form-input" placeholder="${i18n_default.t("filter_placeholder")}" style="width: 100%;" />
3078
+ <div class="rq-section" style="margin-bottom: 16px; display: flex; gap: 8px; flex-wrap: wrap; align-items: center;">
3079
+ <input type="text" class="rq-filter-text rq-form-input" placeholder="${i18n_default.t("filter_placeholder")}" style="flex: 1; min-width: 150px;" />
3080
+ <select class="rq-filter-method rq-form-select" style="min-width: 100px;">
3081
+ <option value="">${i18n_default.t("all_methods")}</option>
3082
+ <option value="GET">GET</option>
3083
+ <option value="POST">POST</option>
3084
+ <option value="PUT">PUT</option>
3085
+ <option value="PATCH">PATCH</option>
3086
+ <option value="DELETE">DELETE</option>
3087
+ </select>
3088
+ <select class="rq-filter-status rq-form-select" style="min-width: 100px;">
3089
+ <option value="">${i18n_default.t("all_statuses")}</option>
3090
+ <option value="2xx">2xx ${i18n_default.t("status_success")}</option>
3091
+ <option value="4xx">4xx ${i18n_default.t("status_client_error")}</option>
3092
+ <option value="5xx">5xx ${i18n_default.t("status_server_error")}</option>
3093
+ <option value="error">${i18n_default.t("error_label")}</option>
3094
+ </select>
3095
+ <button class="rq-filter-clear rq-btn" style="padding: 8px 12px; font-size: 12px;">${i18n_default.t("clear_form")}</button>
2645
3096
  </div>
2646
3097
  <div class="rq-list"></div>
2647
3098
  `;
@@ -2651,15 +3102,111 @@ function renderHistory(container) {
2651
3102
  list.innerHTML = `<div class="rq-empty" style="min-height: 200px;"><p>${i18n_default.t("no_matching_requests")}</p></div>`;
2652
3103
  return;
2653
3104
  }
2654
- list.innerHTML = items.map((e) => formatHistoryCard(e)).join("");
2655
- }
2656
- const filter = main.querySelector(".rq-filter");
2657
- filter.addEventListener("input", () => {
2658
- const q = filter.value.toLowerCase();
2659
- const filtered = entries.filter(
2660
- (e) => (e.method || "").toLowerCase().includes(q) || (e.status || "").toString().includes(q) || (e.url || "").toLowerCase().includes(q) || (e.page || "").toLowerCase().includes(q)
2661
- );
3105
+ let html = "";
3106
+ if (config2.groupBy && (config2.groupBy === "url" || config2.groupBy === "method" || config2.groupBy === "status" || config2.groupBy === "page")) {
3107
+ const groups = {};
3108
+ for (const item of items) {
3109
+ let key = "";
3110
+ if (config2.groupBy === "url") key = item.url || "unknown";
3111
+ else if (config2.groupBy === "method") key = item.method || "GET";
3112
+ else if (config2.groupBy === "status") key = item.status ? item.status >= 400 ? "Error" : "Success" : "Pending";
3113
+ else if (config2.groupBy === "page") key = item.page || "unknown";
3114
+ if (!groups[key]) groups[key] = [];
3115
+ groups[key].push(item);
3116
+ }
3117
+ for (const [key, groupItems] of Object.entries(groups)) {
3118
+ const count = groupItems.length;
3119
+ const groupId = `group-${key.replace(/[^a-z0-9]/gi, "-")}`;
3120
+ html += `
3121
+ <div class="rq-group">
3122
+ <div class="rq-group-header" data-group-id="${groupId}">
3123
+ <span class="rq-group-toggle">\u25BC</span>
3124
+ <span style="flex: 1; text-align: left;">${escapeHtml(key)} (${count})</span>
3125
+ </div>
3126
+ <div class="rq-group-items" data-group-id="${groupId}">
3127
+ ${groupItems.map((e) => formatHistoryCard(e)).join("")}
3128
+ </div>
3129
+ </div>
3130
+ `;
3131
+ }
3132
+ } else {
3133
+ html = items.map((e) => formatHistoryCard(e)).join("");
3134
+ }
3135
+ list.innerHTML = html;
3136
+ if (config2.groupBy) {
3137
+ const headers = list.querySelectorAll(".rq-group-header");
3138
+ headers.forEach((header) => {
3139
+ header.addEventListener("click", () => {
3140
+ const groupId = header.getAttribute("data-group-id");
3141
+ const items2 = list.querySelector(`.rq-group-items[data-group-id="${groupId}"]`);
3142
+ const toggle = header.querySelector(".rq-group-toggle");
3143
+ if (items2 && toggle) {
3144
+ items2.classList.toggle("collapsed");
3145
+ toggle.classList.toggle("collapsed");
3146
+ }
3147
+ });
3148
+ });
3149
+ }
3150
+ const sendBtns = list.querySelectorAll(".rq-send-btn");
3151
+ sendBtns.forEach((btn) => {
3152
+ btn.addEventListener("click", () => {
3153
+ const method = btn.getAttribute("data-method") || "GET";
3154
+ const url = btn.getAttribute("data-url") || "";
3155
+ const bodyStr = btn.getAttribute("data-body") || "{}";
3156
+ let body = {};
3157
+ try {
3158
+ body = JSON.parse(bodyStr);
3159
+ } catch (e) {
3160
+ }
3161
+ const panel2 = document.getElementById("reqwise-panel");
3162
+ if (!panel2) return;
3163
+ const sendTab = panel2.querySelector('[data-tabname="send"]');
3164
+ if (sendTab) sendTab.click();
3165
+ setTimeout(() => {
3166
+ const form = main.querySelector(".rq-form");
3167
+ if (!form) return;
3168
+ const methodSelect = form.querySelector('[name="method"]');
3169
+ const urlInput = form.querySelector('[name="url"]');
3170
+ const bodyInput = form.querySelector('[name="body"]');
3171
+ if (methodSelect) methodSelect.value = method;
3172
+ if (urlInput) {
3173
+ urlInput.value = url;
3174
+ urlInput.focus();
3175
+ }
3176
+ if (bodyInput && Object.keys(body).length > 0) {
3177
+ bodyInput.value = JSON.stringify(body, null, 2);
3178
+ }
3179
+ }, 50);
3180
+ });
3181
+ });
3182
+ }
3183
+ function applyFilters() {
3184
+ const searchQ = main.querySelector(".rq-filter-text").value.toLowerCase();
3185
+ const methodF = main.querySelector(".rq-filter-method").value;
3186
+ const statusF = main.querySelector(".rq-filter-status").value;
3187
+ const filtered = entries.filter((e) => {
3188
+ if (searchQ && !((e.method || "").toLowerCase().includes(searchQ) || (e.status || "").toString().includes(searchQ) || (e.url || "").toLowerCase().includes(searchQ) || (e.page || "").toLowerCase().includes(searchQ))) return false;
3189
+ if (methodF && (e.method || "GET").toUpperCase() !== methodF.toUpperCase()) return false;
3190
+ if (statusF === "error" && !e.error) return false;
3191
+ if (statusF === "2xx" && (!e.status || e.status < 200 || e.status >= 300)) return false;
3192
+ if (statusF === "4xx" && (!e.status || e.status < 400 || e.status >= 500)) return false;
3193
+ if (statusF === "5xx" && (!e.status || e.status < 500)) return false;
3194
+ return true;
3195
+ });
2662
3196
  renderList(filtered);
3197
+ }
3198
+ const filterText = main.querySelector(".rq-filter-text");
3199
+ const filterMethod = main.querySelector(".rq-filter-method");
3200
+ const filterStatus = main.querySelector(".rq-filter-status");
3201
+ const filterClear = main.querySelector(".rq-filter-clear");
3202
+ filterText.addEventListener("input", applyFilters);
3203
+ filterMethod.addEventListener("change", applyFilters);
3204
+ filterStatus.addEventListener("change", applyFilters);
3205
+ filterClear.addEventListener("click", () => {
3206
+ filterText.value = "";
3207
+ filterMethod.value = "";
3208
+ filterStatus.value = "";
3209
+ applyFilters();
2663
3210
  });
2664
3211
  renderList(entries);
2665
3212
  }
@@ -2667,14 +3214,21 @@ function formatHistoryCard(e) {
2667
3214
  const statusBadge = getStatusBadge(e.status);
2668
3215
  const duration = e.duration ? `${e.duration}ms` : "\u2014";
2669
3216
  const statusText = e.statusText ? e.statusText : "";
3217
+ const entryId = e.id || "";
3218
+ let highlightClass = "";
3219
+ if (config2.highlight === "error" && e.status && (e.status >= 400 || e.error)) {
3220
+ highlightClass = "rq-error";
3221
+ } else if (config2.highlight === "slow" && e.duration && e.duration > 500) {
3222
+ highlightClass = "rq-slow";
3223
+ }
2670
3224
  return `
2671
- <div class="rq-card" style="border: 1px solid var(--rq-border); border-radius: 8px; padding: 16px; margin-bottom: 12px;">
3225
+ <div class="rq-card ${highlightClass}" style="border: 1px solid var(--rq-border); border-radius: 8px; padding: 16px; margin-bottom: 12px;">
2672
3226
  <div class="rq-card-header">
2673
3227
  <h4 class="rq-card-title">${e.method || "GET"} ${extractPath(e.url)}</h4>
2674
3228
  ${statusBadge}
2675
3229
  ${e.source === "manual" ? '<span class="rq-badge">' + i18n_default.t("manual_badge") + "</span>" : ""}
2676
3230
  </div>
2677
-
3231
+
2678
3232
  <div class="rq-meta" style="gap: 12px; margin-top: 8px;">
2679
3233
  <div class="rq-meta-item">
2680
3234
  <span class="rq-meta-label">${i18n_default.t("endpoint_label")}:</span>
@@ -2691,6 +3245,10 @@ function formatHistoryCard(e) {
2691
3245
  <code class="rq-meta-code">${new Date(e.timestamp).toLocaleTimeString()}</code>
2692
3246
  </div>
2693
3247
  </div>
3248
+
3249
+ <div style="margin-top: 12px; display: flex; gap: 8px;">
3250
+ <button class="rq-btn primary rq-send-btn" data-entry-id="${entryId}" data-method="${escapeHtml(e.method || "GET")}" data-url="${escapeHtml(e.url)}" data-body="${escapeHtml(JSON.stringify(e.requestBody || {}))}" style="font-size: 12px; padding: 6px 12px; flex: 1;">\u2192 ${i18n_default.t("send_request")}</button>
3251
+ </div>
2694
3252
  </div>
2695
3253
  `;
2696
3254
  }
@@ -2833,10 +3391,13 @@ function renderEndpoints(container) {
2833
3391
  `;
2834
3392
  }).join("");
2835
3393
  const examples = (e.examples || []).slice(0, 3).map((ex) => `<code class="rq-meta-code">${escapeHtml(ex)}</code>`).join("<br/>");
3394
+ const methodsArray = Object.keys(e.methods || {});
3395
+ const primaryMethod = methodsArray.length > 0 ? methodsArray[0] : "GET";
3396
+ const fullUrl = e.fullPath || (e.origin ? e.origin + e.path : e.path);
2836
3397
  return `
2837
3398
  <div class="rq-card" style="border: 1px solid var(--rq-border); border-radius: 8px; padding: 16px; margin-bottom: 12px;">
2838
3399
  <div class="rq-card-header">
2839
- <h4 class="rq-card-title">${escapeHtml(e.path)}</h4>
3400
+ <h4 class="rq-card-title" style="word-break: break-all;">${escapeHtml(fullUrl)}</h4>
2840
3401
  <span style="background: var(--rq-bg-secondary); padding: 4px 12px; border-radius: 4px; font-size: 12px; color: var(--rq-fg-secondary);">${e.count || 0} ${i18n_default.t("hits")}</span>
2841
3402
  </div>
2842
3403
 
@@ -2860,10 +3421,36 @@ function renderEndpoints(container) {
2860
3421
  <div style="margin-top: 12px; font-size: 12px; color: var(--rq-fg-secondary);">
2861
3422
  ${i18n_default.t("last_seen")}: ${new Date(e.lastSeen).toLocaleTimeString()}
2862
3423
  </div>
3424
+
3425
+ <div style="margin-top: 12px; display: flex; gap: 8px;">
3426
+ <button class="rq-btn primary rq-endpoint-send-btn" data-method="${escapeHtml(primaryMethod)}" data-url="${escapeHtml(fullUrl)}" style="font-size: 12px; padding: 6px 12px; flex: 1;">\u2192 ${i18n_default.t("send_request")}</button>
3427
+ </div>
2863
3428
  </div>
2864
3429
  `;
2865
3430
  }).join("");
2866
3431
  main.innerHTML = html;
3432
+ const endpointSendBtns = main.querySelectorAll(".rq-endpoint-send-btn");
3433
+ endpointSendBtns.forEach((btn) => {
3434
+ btn.addEventListener("click", () => {
3435
+ const method = btn.getAttribute("data-method") || "GET";
3436
+ const url = btn.getAttribute("data-url") || "/";
3437
+ const panel2 = document.getElementById("reqwise-panel");
3438
+ if (!panel2) return;
3439
+ const sendTab = panel2.querySelector('[data-tabname="send"]');
3440
+ if (sendTab) sendTab.click();
3441
+ setTimeout(() => {
3442
+ const form = main.querySelector(".rq-form");
3443
+ if (!form) return;
3444
+ const methodSelect = form.querySelector('[name="method"]');
3445
+ const urlInput = form.querySelector('[name="url"]');
3446
+ if (methodSelect) methodSelect.value = method;
3447
+ if (urlInput) {
3448
+ urlInput.value = url;
3449
+ urlInput.focus();
3450
+ }
3451
+ }, 50);
3452
+ });
3453
+ });
2867
3454
  }
2868
3455
  function renderer(container) {
2869
3456
  try {
@@ -2910,6 +3497,7 @@ export {
2910
3497
  i18n_default as i18n,
2911
3498
  panel_default as panel,
2912
3499
  renderer_default as renderer,
3500
+ setConfig2 as rendererSetConfig,
2913
3501
  storage_default as storage
2914
3502
  };
2915
3503
  //# sourceMappingURL=index.mjs.map