@testsmith/api-spector 0.1.9 → 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.
- package/out/main/chunks/{request-handler-DAXUMRyd.js → request-handler-AFBOd__c.js} +209 -11
- package/out/main/index.js +148 -19
- package/out/main/runner.js +54 -18
- package/out/preload/index.js +4 -0
- package/out/renderer/assets/{index-DheIaFRx.js → index-CnjhlKQP.js} +1679 -510
- package/out/renderer/assets/index-FZtc_UAN.css +2 -0
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
- package/out/renderer/assets/index-BhOUavjZ.css +0 -2
|
@@ -13340,10 +13340,10 @@ function makeCollection(name2) {
|
|
|
13340
13340
|
requests: {}
|
|
13341
13341
|
};
|
|
13342
13342
|
}
|
|
13343
|
-
function findFolder(root2, id2) {
|
|
13343
|
+
function findFolder$1(root2, id2) {
|
|
13344
13344
|
if (root2.id === id2) return root2;
|
|
13345
13345
|
for (const sub of root2.folders) {
|
|
13346
|
-
const found = findFolder(sub, id2);
|
|
13346
|
+
const found = findFolder$1(sub, id2);
|
|
13347
13347
|
if (found) return found;
|
|
13348
13348
|
}
|
|
13349
13349
|
return null;
|
|
@@ -13497,6 +13497,16 @@ const useStore = create()(
|
|
|
13497
13497
|
s.activeCollectionId = next?.collectionId ?? null;
|
|
13498
13498
|
}
|
|
13499
13499
|
}),
|
|
13500
|
+
closeAllTabs: () => set2((s) => {
|
|
13501
|
+
s.tabs = [];
|
|
13502
|
+
s.activeTabId = null;
|
|
13503
|
+
}),
|
|
13504
|
+
closeOtherTabs: (keepTabId) => set2((s) => {
|
|
13505
|
+
const kept = s.tabs.find((t2) => t2.id === keepTabId);
|
|
13506
|
+
s.tabs = kept ? [kept] : [];
|
|
13507
|
+
s.activeTabId = kept?.id ?? null;
|
|
13508
|
+
if (kept) s.activeCollectionId = kept.collectionId;
|
|
13509
|
+
}),
|
|
13500
13510
|
setActiveTabId: (id2) => set2((s) => {
|
|
13501
13511
|
s.activeTabId = id2;
|
|
13502
13512
|
const tab = s.tabs.find((t2) => t2.id === id2);
|
|
@@ -13624,6 +13634,42 @@ const useStore = create()(
|
|
|
13624
13634
|
s.activeCollectionId = newId;
|
|
13625
13635
|
if (s.workspace) s.workspace.collections.push(relPath);
|
|
13626
13636
|
}),
|
|
13637
|
+
mergeIntoCollection: (collectionId, sourceFolder, sourceRequests) => set2((s) => {
|
|
13638
|
+
const entry = s.collections[collectionId];
|
|
13639
|
+
if (!entry) return;
|
|
13640
|
+
const col = entry.data;
|
|
13641
|
+
const cloned = JSON.parse(JSON.stringify(sourceFolder));
|
|
13642
|
+
function remapFolder(f) {
|
|
13643
|
+
f.id = v4();
|
|
13644
|
+
f.requestIds = f.requestIds.map((oldId) => {
|
|
13645
|
+
const newId = v4();
|
|
13646
|
+
const srcReq = sourceRequests[oldId];
|
|
13647
|
+
if (srcReq) col.requests[newId] = { ...srcReq, id: newId };
|
|
13648
|
+
return newId;
|
|
13649
|
+
});
|
|
13650
|
+
f.folders.forEach(remapFolder);
|
|
13651
|
+
}
|
|
13652
|
+
remapFolder(cloned);
|
|
13653
|
+
if (cloned.folders.length > 0) {
|
|
13654
|
+
for (const sub of cloned.folders) {
|
|
13655
|
+
col.rootFolder.folders.push(sub);
|
|
13656
|
+
}
|
|
13657
|
+
if (cloned.requestIds.length > 0) {
|
|
13658
|
+
const wrapper = {
|
|
13659
|
+
id: v4(),
|
|
13660
|
+
name: cloned.name || "Imported",
|
|
13661
|
+
description: "",
|
|
13662
|
+
folders: [],
|
|
13663
|
+
requestIds: cloned.requestIds
|
|
13664
|
+
};
|
|
13665
|
+
col.rootFolder.folders.push(wrapper);
|
|
13666
|
+
}
|
|
13667
|
+
} else {
|
|
13668
|
+
col.rootFolder.folders.push(cloned);
|
|
13669
|
+
}
|
|
13670
|
+
entry.dirty = true;
|
|
13671
|
+
s.activeCollectionId = collectionId;
|
|
13672
|
+
}),
|
|
13627
13673
|
deleteCollection: (id2) => set2((s) => {
|
|
13628
13674
|
const relPath = s.collections[id2]?.relPath;
|
|
13629
13675
|
delete s.collections[id2];
|
|
@@ -13657,7 +13703,7 @@ const useStore = create()(
|
|
|
13657
13703
|
addFolder: (collectionId, parentFolderId, name2) => set2((s) => {
|
|
13658
13704
|
const col = s.collections[collectionId]?.data;
|
|
13659
13705
|
if (!col) return;
|
|
13660
|
-
const parent = findFolder(col.rootFolder, parentFolderId);
|
|
13706
|
+
const parent = findFolder$1(col.rootFolder, parentFolderId);
|
|
13661
13707
|
if (!parent) return;
|
|
13662
13708
|
parent.folders.push({ id: v4(), name: name2, description: "", folders: [], requestIds: [] });
|
|
13663
13709
|
s.collections[collectionId].dirty = true;
|
|
@@ -13665,7 +13711,7 @@ const useStore = create()(
|
|
|
13665
13711
|
renameFolder: (collectionId, folderId, name2) => set2((s) => {
|
|
13666
13712
|
const col = s.collections[collectionId]?.data;
|
|
13667
13713
|
if (!col) return;
|
|
13668
|
-
const folder = findFolder(col.rootFolder, folderId);
|
|
13714
|
+
const folder = findFolder$1(col.rootFolder, folderId);
|
|
13669
13715
|
if (folder) {
|
|
13670
13716
|
folder.name = name2;
|
|
13671
13717
|
s.collections[collectionId].dirty = true;
|
|
@@ -13674,7 +13720,7 @@ const useStore = create()(
|
|
|
13674
13720
|
duplicateFolder: (collectionId, folderId) => set2((s) => {
|
|
13675
13721
|
const col = s.collections[collectionId]?.data;
|
|
13676
13722
|
if (!col) return;
|
|
13677
|
-
const orig = findFolder(col.rootFolder, folderId);
|
|
13723
|
+
const orig = findFolder$1(col.rootFolder, folderId);
|
|
13678
13724
|
if (!orig) return;
|
|
13679
13725
|
const copy = JSON.parse(JSON.stringify(orig));
|
|
13680
13726
|
copy.name = orig.name + " (copy)";
|
|
@@ -13703,7 +13749,7 @@ const useStore = create()(
|
|
|
13703
13749
|
function collectIds(f) {
|
|
13704
13750
|
return [...f.requestIds, ...f.folders.flatMap(collectIds)];
|
|
13705
13751
|
}
|
|
13706
|
-
const folder = findFolder(col.rootFolder, folderId);
|
|
13752
|
+
const folder = findFolder$1(col.rootFolder, folderId);
|
|
13707
13753
|
if (folder) {
|
|
13708
13754
|
collectIds(folder).forEach((rid) => delete col.requests[rid]);
|
|
13709
13755
|
}
|
|
@@ -13717,7 +13763,7 @@ const useStore = create()(
|
|
|
13717
13763
|
const col = s.collections[collectionId]?.data;
|
|
13718
13764
|
if (!col) return;
|
|
13719
13765
|
col.requests[req.id] = req;
|
|
13720
|
-
const folder = findFolder(col.rootFolder, folderId) ?? col.rootFolder;
|
|
13766
|
+
const folder = findFolder$1(col.rootFolder, folderId) ?? col.rootFolder;
|
|
13721
13767
|
folder.requestIds.push(req.id);
|
|
13722
13768
|
s.activeCollectionId = collectionId;
|
|
13723
13769
|
s.collections[collectionId].dirty = true;
|
|
@@ -13788,7 +13834,7 @@ const useStore = create()(
|
|
|
13788
13834
|
const tab = s.tabs.find((t2) => t2.requestId === requestId);
|
|
13789
13835
|
if (tab) tab.collectionId = destCollectionId;
|
|
13790
13836
|
}
|
|
13791
|
-
const destFolder = findFolder(destCol.rootFolder, destFolderId);
|
|
13837
|
+
const destFolder = findFolder$1(destCol.rootFolder, destFolderId);
|
|
13792
13838
|
if (destFolder) {
|
|
13793
13839
|
if (destIndex !== void 0) {
|
|
13794
13840
|
let adjusted = destIndex;
|
|
@@ -13803,11 +13849,33 @@ const useStore = create()(
|
|
|
13803
13849
|
}
|
|
13804
13850
|
s.collections[destCollectionId].dirty = true;
|
|
13805
13851
|
}),
|
|
13852
|
+
moveFolder: (collectionId, folderId, destParentFolderId, destIndex) => set2((s) => {
|
|
13853
|
+
const col = s.collections[collectionId]?.data;
|
|
13854
|
+
if (!col) return;
|
|
13855
|
+
const folder = findFolder$1(col.rootFolder, folderId);
|
|
13856
|
+
if (!folder) return;
|
|
13857
|
+
if (folderId === destParentFolderId) return;
|
|
13858
|
+
if (findFolder$1(folder, destParentFolderId)) return;
|
|
13859
|
+
const srcParent = findFolderParent(col.rootFolder, folderId) ?? col.rootFolder;
|
|
13860
|
+
const srcIdx = srcParent.folders.findIndex((f) => f.id === folderId);
|
|
13861
|
+
srcParent.folders.splice(srcIdx, 1);
|
|
13862
|
+
const destParent = findFolder$1(col.rootFolder, destParentFolderId);
|
|
13863
|
+
if (!destParent) return;
|
|
13864
|
+
if (destIndex !== void 0) {
|
|
13865
|
+
let adjusted = destIndex;
|
|
13866
|
+
if (srcParent.id === destParent.id && srcIdx < destIndex) adjusted--;
|
|
13867
|
+
adjusted = Math.max(0, Math.min(adjusted, destParent.folders.length));
|
|
13868
|
+
destParent.folders.splice(adjusted, 0, folder);
|
|
13869
|
+
} else {
|
|
13870
|
+
destParent.folders.push(folder);
|
|
13871
|
+
}
|
|
13872
|
+
s.collections[collectionId].dirty = true;
|
|
13873
|
+
}),
|
|
13806
13874
|
// ── Tags ──────────────────────────────────────────────────────────────────
|
|
13807
13875
|
updateFolderTags: (collectionId, folderId, tags2) => set2((s) => {
|
|
13808
13876
|
const col = s.collections[collectionId]?.data;
|
|
13809
13877
|
if (!col) return;
|
|
13810
|
-
const folder = findFolder(col.rootFolder, folderId);
|
|
13878
|
+
const folder = findFolder$1(col.rootFolder, folderId);
|
|
13811
13879
|
if (folder) {
|
|
13812
13880
|
folder.tags = tags2;
|
|
13813
13881
|
s.collections[collectionId].dirty = true;
|
|
@@ -13824,7 +13892,7 @@ const useStore = create()(
|
|
|
13824
13892
|
updateFolder: (collectionId, folderId, patch) => set2((s) => {
|
|
13825
13893
|
const col = s.collections[collectionId]?.data;
|
|
13826
13894
|
if (!col) return;
|
|
13827
|
-
const folder = findFolder(col.rootFolder, folderId);
|
|
13895
|
+
const folder = findFolder$1(col.rootFolder, folderId);
|
|
13828
13896
|
if (folder) {
|
|
13829
13897
|
Object.assign(folder, patch);
|
|
13830
13898
|
s.collections[collectionId].dirty = true;
|
|
@@ -13904,8 +13972,12 @@ const useStore = create()(
|
|
|
13904
13972
|
if (activeEnvId && s.environments[activeEnvId]) {
|
|
13905
13973
|
const env = s.environments[activeEnvId].data;
|
|
13906
13974
|
for (const [key, value] of Object.entries(result.updatedEnvVars)) {
|
|
13907
|
-
const
|
|
13908
|
-
if (
|
|
13975
|
+
const existing = env.variables.find((v) => v.key === key);
|
|
13976
|
+
if (existing && !existing.secret) {
|
|
13977
|
+
existing.value = value;
|
|
13978
|
+
} else if (!existing) {
|
|
13979
|
+
env.variables.push({ key, value, enabled: true });
|
|
13980
|
+
}
|
|
13909
13981
|
}
|
|
13910
13982
|
}
|
|
13911
13983
|
s.globals = { ...s.globals, ...result.updatedGlobals };
|
|
@@ -14040,7 +14112,7 @@ const useStore = create()(
|
|
|
14040
14112
|
})
|
|
14041
14113
|
}))
|
|
14042
14114
|
);
|
|
14043
|
-
const { electron: electron$
|
|
14115
|
+
const { electron: electron$p } = window;
|
|
14044
14116
|
function useAutoSave() {
|
|
14045
14117
|
const collections = useStore((s) => s.collections);
|
|
14046
14118
|
useStore((s) => s.environments);
|
|
@@ -14056,7 +14128,7 @@ function useAutoSave() {
|
|
|
14056
14128
|
for (const { relPath, data, dirty } of dirtyCollections) {
|
|
14057
14129
|
if (!dirty) continue;
|
|
14058
14130
|
try {
|
|
14059
|
-
await electron$
|
|
14131
|
+
await electron$p.saveCollection(relPath, data);
|
|
14060
14132
|
markCollectionClean(data.id);
|
|
14061
14133
|
} catch (e) {
|
|
14062
14134
|
console.error("Auto-save failed for", relPath, e);
|
|
@@ -14072,7 +14144,7 @@ function useAutoSave() {
|
|
|
14072
14144
|
if (wsTimerRef.current) clearTimeout(wsTimerRef.current);
|
|
14073
14145
|
wsTimerRef.current = setTimeout(async () => {
|
|
14074
14146
|
try {
|
|
14075
|
-
await electron$
|
|
14147
|
+
await electron$p.saveWorkspace(workspace);
|
|
14076
14148
|
} catch {
|
|
14077
14149
|
}
|
|
14078
14150
|
}, 300);
|
|
@@ -14081,7 +14153,7 @@ function useAutoSave() {
|
|
|
14081
14153
|
};
|
|
14082
14154
|
}, [workspace]);
|
|
14083
14155
|
}
|
|
14084
|
-
const { electron: electron$
|
|
14156
|
+
const { electron: electron$o } = window;
|
|
14085
14157
|
function useWorkspaceLoader() {
|
|
14086
14158
|
const loadCollection = useStore((s) => s.loadCollection);
|
|
14087
14159
|
const loadEnvironment = useStore((s) => s.loadEnvironment);
|
|
@@ -14100,28 +14172,28 @@ function useWorkspaceLoader() {
|
|
|
14100
14172
|
});
|
|
14101
14173
|
for (const colPath of ws2.collections) {
|
|
14102
14174
|
try {
|
|
14103
|
-
const col = await electron$
|
|
14175
|
+
const col = await electron$o.loadCollection(colPath);
|
|
14104
14176
|
loadCollection(colPath, col);
|
|
14105
14177
|
} catch {
|
|
14106
14178
|
}
|
|
14107
14179
|
}
|
|
14108
14180
|
for (const envPath of ws2.environments) {
|
|
14109
14181
|
try {
|
|
14110
|
-
const env = await electron$
|
|
14182
|
+
const env = await electron$o.loadEnvironment(envPath);
|
|
14111
14183
|
loadEnvironment(envPath, env);
|
|
14112
14184
|
} catch {
|
|
14113
14185
|
}
|
|
14114
14186
|
}
|
|
14115
14187
|
for (const relPath of ws2.mocks ?? []) {
|
|
14116
14188
|
try {
|
|
14117
|
-
const mockData = await electron$
|
|
14189
|
+
const mockData = await electron$o.loadMock(relPath);
|
|
14118
14190
|
loadMock(relPath, mockData);
|
|
14119
14191
|
} catch {
|
|
14120
14192
|
}
|
|
14121
14193
|
}
|
|
14122
14194
|
if (ws2.collections.length > 0) {
|
|
14123
14195
|
try {
|
|
14124
|
-
const firstCol = await electron$
|
|
14196
|
+
const firstCol = await electron$o.loadCollection(ws2.collections[0]);
|
|
14125
14197
|
setActiveCollection(firstCol.id);
|
|
14126
14198
|
} catch {
|
|
14127
14199
|
}
|
|
@@ -24807,11 +24879,11 @@ class EditContextManager {
|
|
|
24807
24879
|
this.handlers.textformatupdate = (e) => {
|
|
24808
24880
|
let deco = [];
|
|
24809
24881
|
for (let format2 of e.getTextFormats()) {
|
|
24810
|
-
let
|
|
24811
|
-
if (!/none/i.test(
|
|
24882
|
+
let lineStyle2 = format2.underlineStyle, thickness = format2.underlineThickness;
|
|
24883
|
+
if (!/none/i.test(lineStyle2) && !/none/i.test(thickness)) {
|
|
24812
24884
|
let from = this.toEditorPos(format2.rangeStart), to = this.toEditorPos(format2.rangeEnd);
|
|
24813
24885
|
if (from < to) {
|
|
24814
|
-
let style2 = `text-decoration: underline ${/^[a-z]/.test(
|
|
24886
|
+
let style2 = `text-decoration: underline ${/^[a-z]/.test(lineStyle2) ? lineStyle2 + " " : lineStyle2 == "Dashed" ? "dashed " : lineStyle2 == "Squiggle" ? "wavy " : ""}${/thin/i.test(thickness) ? 1 : 2}px`;
|
|
24815
24887
|
deco.push(Decoration.mark({ attributes: { style: style2 } }).range(from, to));
|
|
24816
24888
|
}
|
|
24817
24889
|
}
|
|
@@ -26191,9 +26263,9 @@ function rectanglesForRange(view, className, range) {
|
|
|
26191
26263
|
let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
|
|
26192
26264
|
let ltr = view.textDirection == Direction.LTR;
|
|
26193
26265
|
let content2 = view.contentDOM, contentRect = content2.getBoundingClientRect(), base2 = getBase(view);
|
|
26194
|
-
let lineElt = content2.querySelector(".cm-line"),
|
|
26195
|
-
let leftSide = contentRect.left + (
|
|
26196
|
-
let rightSide = contentRect.right - (
|
|
26266
|
+
let lineElt = content2.querySelector(".cm-line"), lineStyle2 = lineElt && window.getComputedStyle(lineElt);
|
|
26267
|
+
let leftSide = contentRect.left + (lineStyle2 ? parseInt(lineStyle2.paddingLeft) + Math.min(0, parseInt(lineStyle2.textIndent)) : 0);
|
|
26268
|
+
let rightSide = contentRect.right - (lineStyle2 ? parseInt(lineStyle2.paddingRight) : 0);
|
|
26197
26269
|
let startBlock = blockAt(view, from, 1), endBlock = blockAt(view, to, -1);
|
|
26198
26270
|
let visualStart = startBlock.type == BlockType.Text ? startBlock : null;
|
|
26199
26271
|
let visualEnd = endBlock.type == BlockType.Text ? endBlock : null;
|
|
@@ -34901,7 +34973,7 @@ const HEADER_VALUE_SUGGESTIONS = {
|
|
|
34901
34973
|
function getValueSuggestions(headerName) {
|
|
34902
34974
|
return HEADER_VALUE_SUGGESTIONS[headerName.toLowerCase()];
|
|
34903
34975
|
}
|
|
34904
|
-
function KVTable({ rows, onChange, keyPlaceholder = "Key", valuePlaceholder = "Value", headerMode }) {
|
|
34976
|
+
function KVTable({ rows, onChange, keyPlaceholder = "Key", valuePlaceholder = "Value", headerMode, paramMode }) {
|
|
34905
34977
|
const [descVisible, setDescVisible] = reactExports.useState(
|
|
34906
34978
|
() => new Set(rows.map((r, i) => r.description ? i : -1).filter((i) => i >= 0))
|
|
34907
34979
|
);
|
|
@@ -34948,6 +35020,19 @@ function KVTable({ rows, onChange, keyPlaceholder = "Key", valuePlaceholder = "V
|
|
|
34948
35020
|
className: "accent-blue-500 flex-shrink-0"
|
|
34949
35021
|
}
|
|
34950
35022
|
),
|
|
35023
|
+
paramMode && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
35024
|
+
"select",
|
|
35025
|
+
{
|
|
35026
|
+
value: row.paramType ?? "query",
|
|
35027
|
+
onChange: (e) => update(idx, { paramType: e.target.value }),
|
|
35028
|
+
title: (row.paramType ?? "query") === "path" ? "Path variable — substituted into the URL via {{name}}" : "Query string parameter — appended as ?key=value",
|
|
35029
|
+
className: `flex-shrink-0 text-[10px] bg-surface-800 border border-surface-700 rounded px-1.5 py-1 focus:outline-none focus:border-blue-500 font-mono ${(row.paramType ?? "query") === "path" ? "text-violet-400" : "text-surface-400"}`,
|
|
35030
|
+
children: [
|
|
35031
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "query", children: "query" }),
|
|
35032
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "path", children: "path" })
|
|
35033
|
+
]
|
|
35034
|
+
}
|
|
35035
|
+
),
|
|
34951
35036
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
34952
35037
|
VarInput,
|
|
34953
35038
|
{
|
|
@@ -35527,8 +35612,352 @@ function CollectionAuthPanel({ auth, onChange }) {
|
|
|
35527
35612
|
] }) })
|
|
35528
35613
|
] });
|
|
35529
35614
|
}
|
|
35615
|
+
const { electron: electron$n } = window;
|
|
35616
|
+
function normalisePath(url) {
|
|
35617
|
+
let path = url.replace(/^\{\{[^}]+\}\}/, "").replace(/^https?:\/\/[^/]+/, "");
|
|
35618
|
+
if (!path.startsWith("/")) path = "/" + path;
|
|
35619
|
+
path = path.split("?")[0];
|
|
35620
|
+
path = path.replace(/\{\{([^}]+)\}\}/g, "{$1}");
|
|
35621
|
+
return path;
|
|
35622
|
+
}
|
|
35623
|
+
function collectRequestIds(folder) {
|
|
35624
|
+
const ids = new Set(folder.requestIds);
|
|
35625
|
+
for (const sub of folder.folders) {
|
|
35626
|
+
for (const id2 of collectRequestIds(sub)) ids.add(id2);
|
|
35627
|
+
}
|
|
35628
|
+
return ids;
|
|
35629
|
+
}
|
|
35630
|
+
function findFolder(root2, id2) {
|
|
35631
|
+
if (root2.id === id2) return root2;
|
|
35632
|
+
for (const sub of root2.folders) {
|
|
35633
|
+
const found = findFolder(sub, id2);
|
|
35634
|
+
if (found) return found;
|
|
35635
|
+
}
|
|
35636
|
+
return null;
|
|
35637
|
+
}
|
|
35638
|
+
function SchemaSyncModal({
|
|
35639
|
+
collectionId,
|
|
35640
|
+
scope: scope2 = { type: "collection" },
|
|
35641
|
+
onClose
|
|
35642
|
+
}) {
|
|
35643
|
+
const collections = useStore((s) => s.collections);
|
|
35644
|
+
const updateRequest = useStore((s) => s.updateRequest);
|
|
35645
|
+
const markCollectionClean = useStore((s) => s.markCollectionClean);
|
|
35646
|
+
const col = collections[collectionId]?.data;
|
|
35647
|
+
const [url, setUrl] = reactExports.useState("");
|
|
35648
|
+
const [loading, setLoading] = reactExports.useState(false);
|
|
35649
|
+
const [error2, setError] = reactExports.useState(null);
|
|
35650
|
+
const [specEntries, setSpecEntries] = reactExports.useState(null);
|
|
35651
|
+
const [selected, setSelected] = reactExports.useState(/* @__PURE__ */ new Set());
|
|
35652
|
+
const scopeRequestIds = reactExports.useMemo(() => {
|
|
35653
|
+
if (!col) return null;
|
|
35654
|
+
if (scope2.type === "request") return /* @__PURE__ */ new Set([scope2.requestId]);
|
|
35655
|
+
if (scope2.type === "folder") {
|
|
35656
|
+
const folder = findFolder(col.rootFolder, scope2.folderId);
|
|
35657
|
+
return folder ? collectRequestIds(folder) : /* @__PURE__ */ new Set();
|
|
35658
|
+
}
|
|
35659
|
+
return null;
|
|
35660
|
+
}, [col, scope2]);
|
|
35661
|
+
const matches = reactExports.useMemo(() => {
|
|
35662
|
+
if (!specEntries || !col) return [];
|
|
35663
|
+
const allRequests = Object.values(col.requests);
|
|
35664
|
+
const requests = scopeRequestIds ? allRequests.filter((r) => scopeRequestIds.has(r.id)) : allRequests;
|
|
35665
|
+
const result = [];
|
|
35666
|
+
for (const spec of specEntries) {
|
|
35667
|
+
const specPath = spec.pathTemplate.toLowerCase();
|
|
35668
|
+
const match = requests.find((r) => {
|
|
35669
|
+
if (r.method !== spec.method) return false;
|
|
35670
|
+
return normalisePath(r.url).toLowerCase() === specPath;
|
|
35671
|
+
});
|
|
35672
|
+
if (match) {
|
|
35673
|
+
result.push({
|
|
35674
|
+
specEntry: spec,
|
|
35675
|
+
request: match,
|
|
35676
|
+
oldSchema: match.schema ?? "",
|
|
35677
|
+
newSchema: spec.schema,
|
|
35678
|
+
changed: (match.schema ?? "").trim() !== spec.schema.trim()
|
|
35679
|
+
});
|
|
35680
|
+
}
|
|
35681
|
+
}
|
|
35682
|
+
return result;
|
|
35683
|
+
}, [specEntries, col, scopeRequestIds]);
|
|
35684
|
+
const changedCount = matches.filter((m) => m.changed).length;
|
|
35685
|
+
const unchangedCount = matches.length - changedCount;
|
|
35686
|
+
function autoSelectChanged(entries) {
|
|
35687
|
+
const allRequests = Object.values(col.requests);
|
|
35688
|
+
const requests = scopeRequestIds ? allRequests.filter((r) => scopeRequestIds.has(r.id)) : allRequests;
|
|
35689
|
+
setSelected(new Set(
|
|
35690
|
+
entries.filter((e) => {
|
|
35691
|
+
const specPath = e.pathTemplate.toLowerCase();
|
|
35692
|
+
const match = requests.find((r) => r.method === e.method && normalisePath(r.url).toLowerCase() === specPath);
|
|
35693
|
+
return match && (match.schema ?? "").trim() !== e.schema.trim();
|
|
35694
|
+
}).map((e) => `${e.method}:${e.pathTemplate}`)
|
|
35695
|
+
));
|
|
35696
|
+
}
|
|
35697
|
+
const scopeLabel = scope2.type === "request" ? (col ? Object.values(col.requests).find((r) => r.id === scope2.requestId)?.name : "") ?? "request" : scope2.type === "folder" ? findFolder(col?.rootFolder, scope2.folderId)?.name ?? "folder" : col?.name ?? "collection";
|
|
35698
|
+
async function loadFromFile() {
|
|
35699
|
+
setLoading(true);
|
|
35700
|
+
setError(null);
|
|
35701
|
+
try {
|
|
35702
|
+
const entries = await electron$n.extractOpenApiSchemas();
|
|
35703
|
+
if (!entries) {
|
|
35704
|
+
setLoading(false);
|
|
35705
|
+
return;
|
|
35706
|
+
}
|
|
35707
|
+
setSpecEntries(entries);
|
|
35708
|
+
autoSelectChanged(entries);
|
|
35709
|
+
} catch (err) {
|
|
35710
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
35711
|
+
} finally {
|
|
35712
|
+
setLoading(false);
|
|
35713
|
+
}
|
|
35714
|
+
}
|
|
35715
|
+
async function loadFromUrl() {
|
|
35716
|
+
const trimmed = url.trim();
|
|
35717
|
+
if (!trimmed) return;
|
|
35718
|
+
setLoading(true);
|
|
35719
|
+
setError(null);
|
|
35720
|
+
try {
|
|
35721
|
+
const entries = await electron$n.extractOpenApiSchemasFromUrl(trimmed);
|
|
35722
|
+
setSpecEntries(entries);
|
|
35723
|
+
autoSelectChanged(entries);
|
|
35724
|
+
} catch (err) {
|
|
35725
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
35726
|
+
} finally {
|
|
35727
|
+
setLoading(false);
|
|
35728
|
+
}
|
|
35729
|
+
}
|
|
35730
|
+
function toggleEntry(key) {
|
|
35731
|
+
setSelected((prev) => {
|
|
35732
|
+
const next = new Set(prev);
|
|
35733
|
+
if (next.has(key)) next.delete(key);
|
|
35734
|
+
else next.add(key);
|
|
35735
|
+
return next;
|
|
35736
|
+
});
|
|
35737
|
+
}
|
|
35738
|
+
function selectAllChanged() {
|
|
35739
|
+
setSelected(new Set(matches.filter((m) => m.changed).map((m) => `${m.specEntry.method}:${m.specEntry.pathTemplate}`)));
|
|
35740
|
+
}
|
|
35741
|
+
function selectNone() {
|
|
35742
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
35743
|
+
}
|
|
35744
|
+
async function applySync() {
|
|
35745
|
+
setLoading(true);
|
|
35746
|
+
try {
|
|
35747
|
+
for (const m of matches) {
|
|
35748
|
+
const key = `${m.specEntry.method}:${m.specEntry.pathTemplate}`;
|
|
35749
|
+
if (!selected.has(key)) continue;
|
|
35750
|
+
updateRequest(m.request.id, { schema: m.newSchema });
|
|
35751
|
+
}
|
|
35752
|
+
const entry = useStore.getState().collections[collectionId];
|
|
35753
|
+
if (entry) {
|
|
35754
|
+
await electron$n.saveCollection(entry.relPath, entry.data);
|
|
35755
|
+
markCollectionClean(collectionId);
|
|
35756
|
+
}
|
|
35757
|
+
onClose();
|
|
35758
|
+
} finally {
|
|
35759
|
+
setLoading(false);
|
|
35760
|
+
}
|
|
35761
|
+
}
|
|
35762
|
+
if (!col) return null;
|
|
35763
|
+
if (specEntries) {
|
|
35764
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60", onClick: onClose, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
35765
|
+
"div",
|
|
35766
|
+
{
|
|
35767
|
+
className: "bg-surface-900 border border-surface-700 rounded-xl shadow-2xl w-[640px] max-h-[80vh] p-5 flex flex-col gap-4",
|
|
35768
|
+
onClick: (e) => e.stopPropagation(),
|
|
35769
|
+
children: [
|
|
35770
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
35771
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-sm font-semibold text-surface-100", children: [
|
|
35772
|
+
"Sync schemas — ",
|
|
35773
|
+
scopeLabel
|
|
35774
|
+
] }),
|
|
35775
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "text-surface-500 hover:text-surface-300 text-lg leading-none", children: "×" })
|
|
35776
|
+
] }),
|
|
35777
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 text-xs", children: [
|
|
35778
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-400", children: [
|
|
35779
|
+
specEntries.length,
|
|
35780
|
+
" operations in spec"
|
|
35781
|
+
] }),
|
|
35782
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-400", children: "·" }),
|
|
35783
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-400", children: [
|
|
35784
|
+
matches.length,
|
|
35785
|
+
" matched to existing requests"
|
|
35786
|
+
] }),
|
|
35787
|
+
changedCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
35788
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-400", children: "·" }),
|
|
35789
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-amber-400 font-medium", children: [
|
|
35790
|
+
changedCount,
|
|
35791
|
+
" changed"
|
|
35792
|
+
] })
|
|
35793
|
+
] }),
|
|
35794
|
+
unchangedCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
35795
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-400", children: "·" }),
|
|
35796
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-emerald-400", children: [
|
|
35797
|
+
unchangedCount,
|
|
35798
|
+
" unchanged"
|
|
35799
|
+
] })
|
|
35800
|
+
] })
|
|
35801
|
+
] }),
|
|
35802
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
35803
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[10px] text-surface-500 uppercase tracking-wider font-medium", children: [
|
|
35804
|
+
"Select schemas to update (",
|
|
35805
|
+
selected.size,
|
|
35806
|
+
")"
|
|
35807
|
+
] }),
|
|
35808
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
35809
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: selectAllChanged, className: "text-[10px] text-blue-400 hover:text-blue-300", children: "Select changed" }),
|
|
35810
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: selectNone, className: "text-[10px] text-blue-400 hover:text-blue-300", children: "Select none" })
|
|
35811
|
+
] })
|
|
35812
|
+
] }),
|
|
35813
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-h-0 overflow-y-auto border border-surface-800 rounded-lg", children: [
|
|
35814
|
+
matches.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "p-4 text-xs text-surface-500", children: "No operations from the spec matched any request in this collection. Matching uses HTTP method + URL path." }) : matches.map((m) => {
|
|
35815
|
+
const key = `${m.specEntry.method}:${m.specEntry.pathTemplate}`;
|
|
35816
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
35817
|
+
"label",
|
|
35818
|
+
{
|
|
35819
|
+
className: `flex items-center gap-2 px-3 py-2 hover:bg-surface-850 cursor-pointer border-b border-surface-800 last:border-b-0 ${!m.changed ? "opacity-50" : ""}`,
|
|
35820
|
+
children: [
|
|
35821
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
35822
|
+
"input",
|
|
35823
|
+
{
|
|
35824
|
+
type: "checkbox",
|
|
35825
|
+
checked: selected.has(key),
|
|
35826
|
+
onChange: () => toggleEntry(key),
|
|
35827
|
+
className: "accent-blue-500"
|
|
35828
|
+
}
|
|
35829
|
+
),
|
|
35830
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-mono font-bold w-14 shrink-0 ${methodColor$2(m.specEntry.method)}`, children: m.specEntry.method }),
|
|
35831
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
35832
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-surface-200 truncate", children: m.request.name }),
|
|
35833
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] text-surface-500 font-mono truncate", children: m.specEntry.pathTemplate })
|
|
35834
|
+
] }),
|
|
35835
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] shrink-0 ${m.changed ? "text-amber-400" : "text-emerald-400"}`, children: m.changed ? "changed" : "up to date" })
|
|
35836
|
+
]
|
|
35837
|
+
},
|
|
35838
|
+
key
|
|
35839
|
+
);
|
|
35840
|
+
}),
|
|
35841
|
+
specEntries.length > matches.length && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-2 border-t border-surface-700", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[10px] text-surface-500", children: [
|
|
35842
|
+
specEntries.length - matches.length,
|
|
35843
|
+
" operations not matched (no request with matching method + path)"
|
|
35844
|
+
] }) })
|
|
35845
|
+
] }),
|
|
35846
|
+
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-red-400", children: error2 }),
|
|
35847
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between pt-1", children: [
|
|
35848
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
35849
|
+
"button",
|
|
35850
|
+
{
|
|
35851
|
+
onClick: () => setSpecEntries(null),
|
|
35852
|
+
className: "px-3 py-1.5 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
35853
|
+
children: "Back"
|
|
35854
|
+
}
|
|
35855
|
+
),
|
|
35856
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
35857
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
35858
|
+
"button",
|
|
35859
|
+
{
|
|
35860
|
+
onClick: onClose,
|
|
35861
|
+
className: "px-3 py-1.5 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
35862
|
+
children: "Cancel"
|
|
35863
|
+
}
|
|
35864
|
+
),
|
|
35865
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
35866
|
+
"button",
|
|
35867
|
+
{
|
|
35868
|
+
disabled: loading || selected.size === 0,
|
|
35869
|
+
onClick: applySync,
|
|
35870
|
+
className: "px-3 py-1.5 text-xs bg-blue-700 hover:bg-blue-600 disabled:bg-surface-800 disabled:text-surface-600 rounded transition-colors",
|
|
35871
|
+
children: loading ? "Updating…" : `Update ${selected.size} schema${selected.size !== 1 ? "s" : ""}`
|
|
35872
|
+
}
|
|
35873
|
+
)
|
|
35874
|
+
] })
|
|
35875
|
+
] })
|
|
35876
|
+
]
|
|
35877
|
+
}
|
|
35878
|
+
) });
|
|
35879
|
+
}
|
|
35880
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60", onClick: onClose, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
35881
|
+
"div",
|
|
35882
|
+
{
|
|
35883
|
+
className: "bg-surface-900 border border-surface-700 rounded-xl shadow-2xl w-[420px] p-5 flex flex-col gap-4",
|
|
35884
|
+
onClick: (e) => e.stopPropagation(),
|
|
35885
|
+
children: [
|
|
35886
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
35887
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-sm font-semibold text-surface-100", children: "Sync schemas from OpenAPI" }),
|
|
35888
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "text-surface-500 hover:text-surface-300 text-lg leading-none", children: "×" })
|
|
35889
|
+
] }),
|
|
35890
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-400", children: "Load an OpenAPI spec to update response schemas on existing requests. Matching uses HTTP method + URL path. Only schemas are touched — URLs, params, headers, auth, and scripts are preserved." }),
|
|
35891
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
35892
|
+
"button",
|
|
35893
|
+
{
|
|
35894
|
+
onClick: loadFromFile,
|
|
35895
|
+
disabled: loading,
|
|
35896
|
+
className: "px-3 py-2 text-xs bg-blue-700 hover:bg-blue-600 disabled:bg-surface-800 disabled:text-surface-600 rounded transition-colors font-medium",
|
|
35897
|
+
children: loading ? "Loading…" : "Choose file…"
|
|
35898
|
+
}
|
|
35899
|
+
),
|
|
35900
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
35901
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-500 uppercase tracking-wider font-medium", children: "Or load from URL" }),
|
|
35902
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
35903
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
35904
|
+
"input",
|
|
35905
|
+
{
|
|
35906
|
+
value: url,
|
|
35907
|
+
onChange: (e) => {
|
|
35908
|
+
setUrl(e.target.value);
|
|
35909
|
+
setError(null);
|
|
35910
|
+
},
|
|
35911
|
+
onKeyDown: (e) => {
|
|
35912
|
+
if (e.key === "Enter") loadFromUrl();
|
|
35913
|
+
},
|
|
35914
|
+
placeholder: "https://api.example.com/openapi.json",
|
|
35915
|
+
className: "flex-1 text-xs bg-surface-800 border border-surface-700 rounded px-2.5 py-1.5 focus:outline-none focus:border-blue-500 placeholder-surface-600 font-mono"
|
|
35916
|
+
}
|
|
35917
|
+
),
|
|
35918
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
35919
|
+
"button",
|
|
35920
|
+
{
|
|
35921
|
+
onClick: loadFromUrl,
|
|
35922
|
+
disabled: !url.trim() || loading,
|
|
35923
|
+
className: "px-3 py-1.5 text-xs bg-blue-700 hover:bg-blue-600 disabled:bg-surface-800 disabled:text-surface-600 rounded transition-colors whitespace-nowrap",
|
|
35924
|
+
children: loading ? "Loading…" : "From URL"
|
|
35925
|
+
}
|
|
35926
|
+
)
|
|
35927
|
+
] })
|
|
35928
|
+
] }),
|
|
35929
|
+
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-red-400", children: error2 }),
|
|
35930
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end pt-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
35931
|
+
"button",
|
|
35932
|
+
{
|
|
35933
|
+
onClick: onClose,
|
|
35934
|
+
className: "px-3 py-1.5 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
35935
|
+
children: "Cancel"
|
|
35936
|
+
}
|
|
35937
|
+
) })
|
|
35938
|
+
]
|
|
35939
|
+
}
|
|
35940
|
+
) });
|
|
35941
|
+
}
|
|
35942
|
+
function methodColor$2(method) {
|
|
35943
|
+
switch (method) {
|
|
35944
|
+
case "GET":
|
|
35945
|
+
return "text-emerald-400";
|
|
35946
|
+
case "POST":
|
|
35947
|
+
return "text-amber-400";
|
|
35948
|
+
case "PUT":
|
|
35949
|
+
return "text-sky-400";
|
|
35950
|
+
case "PATCH":
|
|
35951
|
+
return "text-violet-400";
|
|
35952
|
+
case "DELETE":
|
|
35953
|
+
return "text-red-400";
|
|
35954
|
+
default:
|
|
35955
|
+
return "text-surface-300";
|
|
35956
|
+
}
|
|
35957
|
+
}
|
|
35530
35958
|
const DragCtx = reactExports.createContext({ dragging: null, setDragging: () => {
|
|
35531
|
-
},
|
|
35959
|
+
}, onDropRequest: () => {
|
|
35960
|
+
}, onDropFolder: () => {
|
|
35532
35961
|
} });
|
|
35533
35962
|
function InlineEdit({
|
|
35534
35963
|
value,
|
|
@@ -35596,7 +36025,7 @@ function TagChips({
|
|
|
35596
36025
|
if (forceAdding) setAdding(true);
|
|
35597
36026
|
}, [forceAdding]);
|
|
35598
36027
|
function commit() {
|
|
35599
|
-
const t2 = draft.trim()
|
|
36028
|
+
const t2 = draft.trim();
|
|
35600
36029
|
if (t2 && !tags2.includes(t2)) onAdd(t2);
|
|
35601
36030
|
setDraft("");
|
|
35602
36031
|
setAdding(false);
|
|
@@ -35778,6 +36207,7 @@ function CollectionTree() {
|
|
|
35778
36207
|
const updateRequest = useStore((s) => s.updateRequest);
|
|
35779
36208
|
const openRunner = useStore((s) => s.openRunner);
|
|
35780
36209
|
const moveRequest = useStore((s) => s.moveRequest);
|
|
36210
|
+
const moveFolder = useStore((s) => s.moveFolder);
|
|
35781
36211
|
const colList = Object.values(collections);
|
|
35782
36212
|
const [pendingConfirm, setPendingConfirm] = reactExports.useState(null);
|
|
35783
36213
|
const [newRequestId, setNewRequestId] = reactExports.useState(null);
|
|
@@ -35788,12 +36218,18 @@ function CollectionTree() {
|
|
|
35788
36218
|
setPendingConfirm(null);
|
|
35789
36219
|
} });
|
|
35790
36220
|
}
|
|
35791
|
-
function
|
|
35792
|
-
if (!dragging) return;
|
|
36221
|
+
function onDropRequest(destCollectionId, destFolderId, destIndex) {
|
|
36222
|
+
if (!dragging || dragging.type !== "request") return;
|
|
35793
36223
|
moveRequest(dragging.collectionId, dragging.requestId, destCollectionId, destFolderId, destIndex);
|
|
35794
36224
|
setDragging(null);
|
|
35795
36225
|
}
|
|
35796
|
-
|
|
36226
|
+
function onDropFolder(destCollectionId, destParentFolderId, destIndex) {
|
|
36227
|
+
if (!dragging || dragging.type !== "folder") return;
|
|
36228
|
+
if (dragging.collectionId !== destCollectionId) return;
|
|
36229
|
+
moveFolder(dragging.collectionId, dragging.folderId, destParentFolderId, destIndex);
|
|
36230
|
+
setDragging(null);
|
|
36231
|
+
}
|
|
36232
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(DragCtx.Provider, { value: { dragging, setDragging, onDropRequest, onDropFolder }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col flex-1 min-h-0 select-none", children: [
|
|
35797
36233
|
pendingConfirm && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
35798
36234
|
ConfirmDialog,
|
|
35799
36235
|
{
|
|
@@ -35827,6 +36263,10 @@ function CollectionTree() {
|
|
|
35827
36263
|
onUpdateFolderTags: (folderId, tags2) => updateFolderTags(col.id, folderId, tags2),
|
|
35828
36264
|
onUpdateRequestTags: updateRequestTags,
|
|
35829
36265
|
onSetRequestHookType: (reqId, hookType) => updateRequest(reqId, { hookType }),
|
|
36266
|
+
onToggleRequestDisabled: (reqId) => {
|
|
36267
|
+
const r = col.requests[reqId];
|
|
36268
|
+
if (r) updateRequest(reqId, { disabled: !r.disabled });
|
|
36269
|
+
},
|
|
35830
36270
|
onRunCollection: () => openRunner(col.id),
|
|
35831
36271
|
onRunFolder: (folderId) => openRunner(col.id, folderId)
|
|
35832
36272
|
},
|
|
@@ -35862,12 +36302,14 @@ function CollectionNode({
|
|
|
35862
36302
|
onUpdateFolderTags,
|
|
35863
36303
|
onUpdateRequestTags,
|
|
35864
36304
|
onSetRequestHookType,
|
|
36305
|
+
onToggleRequestDisabled,
|
|
35865
36306
|
onRunCollection,
|
|
35866
36307
|
onRunFolder
|
|
35867
36308
|
}) {
|
|
35868
36309
|
const [expanded, setExpanded] = reactExports.useState(true);
|
|
35869
36310
|
const [renaming, setRenaming] = reactExports.useState(false);
|
|
35870
36311
|
const [showSettings, setShowSettings] = reactExports.useState(false);
|
|
36312
|
+
const [showSchemaSync, setShowSchemaSync] = reactExports.useState(false);
|
|
35871
36313
|
const [expandCtrl, setExpandCtrl] = reactExports.useState({ value: true, seq: 0 });
|
|
35872
36314
|
const [dropOver, setDropOver] = reactExports.useState(false);
|
|
35873
36315
|
const dragCtx = reactExports.useContext(DragCtx);
|
|
@@ -35894,7 +36336,8 @@ function CollectionNode({
|
|
|
35894
36336
|
onDrop: (e) => {
|
|
35895
36337
|
e.preventDefault();
|
|
35896
36338
|
setDropOver(false);
|
|
35897
|
-
dragCtx.
|
|
36339
|
+
if (dragCtx.dragging?.type === "folder") dragCtx.onDropFolder(col.id, col.rootFolder.id);
|
|
36340
|
+
else dragCtx.onDropRequest(col.id, col.rootFolder.id);
|
|
35898
36341
|
},
|
|
35899
36342
|
children: [
|
|
35900
36343
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] w-3 text-center shrink-0 mt-0.5", children: expanded ? "▾" : "▸" }),
|
|
@@ -35922,6 +36365,7 @@ function CollectionNode({
|
|
|
35922
36365
|
{ type: "separator" },
|
|
35923
36366
|
{ type: "item", label: "Collection data", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TableIcon, {}), onClick: onSelectCollection },
|
|
35924
36367
|
{ type: "item", label: "Settings", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(GearIcon, {}), onClick: () => setShowSettings(true) },
|
|
36368
|
+
{ type: "item", label: "Sync schemas", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowSchemaSync(true) },
|
|
35925
36369
|
{ type: "item", label: "Rename", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(PencilIcon, {}), onClick: () => setRenaming(true) },
|
|
35926
36370
|
{ type: "item", label: "Duplicate", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: onDuplicateCollection },
|
|
35927
36371
|
{ type: "separator" },
|
|
@@ -35952,15 +36396,19 @@ function CollectionNode({
|
|
|
35952
36396
|
onUpdateFolderTags,
|
|
35953
36397
|
onUpdateRequestTags,
|
|
35954
36398
|
onSetRequestHookType,
|
|
36399
|
+
onToggleRequestDisabled,
|
|
35955
36400
|
onRunFolder
|
|
35956
36401
|
}
|
|
35957
36402
|
),
|
|
35958
|
-
showSettings && /* @__PURE__ */ jsxRuntimeExports.jsx(CollectionSettingsModal, { collection: col, onClose: () => setShowSettings(false) })
|
|
36403
|
+
showSettings && /* @__PURE__ */ jsxRuntimeExports.jsx(CollectionSettingsModal, { collection: col, onClose: () => setShowSettings(false) }),
|
|
36404
|
+
showSchemaSync && /* @__PURE__ */ jsxRuntimeExports.jsx(SchemaSyncModal, { collectionId: col.id, scope: { type: "collection" }, onClose: () => setShowSchemaSync(false) })
|
|
35959
36405
|
] });
|
|
35960
36406
|
}
|
|
35961
36407
|
function FolderRow({
|
|
35962
36408
|
folder,
|
|
35963
36409
|
collectionId,
|
|
36410
|
+
parentFolderId,
|
|
36411
|
+
folderIndex,
|
|
35964
36412
|
depth,
|
|
35965
36413
|
expandCtrl,
|
|
35966
36414
|
onAddRequest,
|
|
@@ -35972,36 +36420,73 @@ function FolderRow({
|
|
|
35972
36420
|
onRun,
|
|
35973
36421
|
children
|
|
35974
36422
|
}) {
|
|
35975
|
-
const [expanded, setExpanded] = reactExports.useState(
|
|
36423
|
+
const [expanded, setExpanded] = reactExports.useState(false);
|
|
35976
36424
|
reactExports.useEffect(() => {
|
|
35977
36425
|
if (expandCtrl.seq > 0) setExpanded(expandCtrl.value);
|
|
35978
36426
|
}, [expandCtrl.seq]);
|
|
35979
36427
|
const [renaming, setRenaming] = reactExports.useState(false);
|
|
35980
36428
|
const [showSettings, setShowSettings] = reactExports.useState(false);
|
|
36429
|
+
const [showSchemaSync, setShowSchemaSync] = reactExports.useState(false);
|
|
35981
36430
|
const [addingTag, setAddingTag] = reactExports.useState(false);
|
|
35982
|
-
const [
|
|
36431
|
+
const [dropPos, setDropPos] = reactExports.useState(null);
|
|
35983
36432
|
const dragCtx = reactExports.useContext(DragCtx);
|
|
35984
36433
|
const tags2 = folder.tags ?? [];
|
|
35985
36434
|
const indent = depth * 12 + 8;
|
|
35986
36435
|
const hasInheritedConfig = folder.auth && folder.auth.type !== "none" || folder.headers && folder.headers.length > 0;
|
|
35987
|
-
|
|
36436
|
+
function handleFolderDragOver(e) {
|
|
36437
|
+
if (!dragCtx.dragging) return;
|
|
36438
|
+
if (dragCtx.dragging.type === "folder" && dragCtx.dragging.folderId === folder.id) return;
|
|
36439
|
+
e.preventDefault();
|
|
36440
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
36441
|
+
const y = e.clientY - rect.top;
|
|
36442
|
+
const zone = y / rect.height;
|
|
36443
|
+
if (dragCtx.dragging.type === "folder") {
|
|
36444
|
+
if (zone < 0.25) setDropPos("before");
|
|
36445
|
+
else if (zone > 0.75) setDropPos("after");
|
|
36446
|
+
else setDropPos("inside");
|
|
36447
|
+
} else {
|
|
36448
|
+
setDropPos("inside");
|
|
36449
|
+
}
|
|
36450
|
+
}
|
|
36451
|
+
function handleFolderDrop(e) {
|
|
36452
|
+
e.preventDefault();
|
|
36453
|
+
e.stopPropagation();
|
|
36454
|
+
if (!dragCtx.dragging) return;
|
|
36455
|
+
if (dragCtx.dragging.type === "folder") {
|
|
36456
|
+
if (dropPos === "inside") {
|
|
36457
|
+
dragCtx.onDropFolder(collectionId, folder.id);
|
|
36458
|
+
} else {
|
|
36459
|
+
const insertIndex = dropPos === "before" ? folderIndex : folderIndex + 1;
|
|
36460
|
+
dragCtx.onDropFolder(collectionId, parentFolderId, insertIndex);
|
|
36461
|
+
}
|
|
36462
|
+
} else {
|
|
36463
|
+
dragCtx.onDropRequest(collectionId, folder.id);
|
|
36464
|
+
}
|
|
36465
|
+
setDropPos(null);
|
|
36466
|
+
}
|
|
36467
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
|
|
36468
|
+
dropPos === "before" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-0 inset-x-0 h-0.5 bg-blue-500 z-10 pointer-events-none" }),
|
|
35988
36469
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
35989
36470
|
"div",
|
|
35990
36471
|
{
|
|
35991
|
-
|
|
36472
|
+
draggable: true,
|
|
36473
|
+
className: `group flex items-start gap-1 py-1 hover:bg-surface-800 transition-colors cursor-pointer text-surface-400 ${dropPos === "inside" ? "outline outline-1 outline-blue-500 rounded" : ""}`,
|
|
35992
36474
|
style: { paddingLeft: indent },
|
|
35993
36475
|
onClick: () => setExpanded((e) => !e),
|
|
35994
|
-
|
|
35995
|
-
e.
|
|
35996
|
-
|
|
35997
|
-
|
|
35998
|
-
|
|
35999
|
-
|
|
36000
|
-
|
|
36001
|
-
|
|
36002
|
-
dragCtx.onDrop(collectionId, folder.id);
|
|
36476
|
+
onDragStart: (e) => {
|
|
36477
|
+
e.dataTransfer.effectAllowed = "move";
|
|
36478
|
+
e.stopPropagation();
|
|
36479
|
+
dragCtx.setDragging({ type: "folder", folderId: folder.id, collectionId });
|
|
36480
|
+
},
|
|
36481
|
+
onDragEnd: () => {
|
|
36482
|
+
dragCtx.setDragging(null);
|
|
36483
|
+
setDropPos(null);
|
|
36003
36484
|
},
|
|
36485
|
+
onDragOver: handleFolderDragOver,
|
|
36486
|
+
onDragLeave: () => setDropPos(null),
|
|
36487
|
+
onDrop: handleFolderDrop,
|
|
36004
36488
|
children: [
|
|
36489
|
+
dropPos === "after" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute bottom-0 inset-x-0 h-0.5 bg-blue-500 z-10 pointer-events-none" }),
|
|
36005
36490
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] w-3 text-center shrink-0 mt-0.5", children: expanded ? "▾" : "▸" }),
|
|
36006
36491
|
/* @__PURE__ */ jsxRuntimeExports.jsx(FolderIcon, { className: `shrink-0 mt-0.5 ${hasInheritedConfig ? "text-blue-500" : "text-amber-600"}` }),
|
|
36007
36492
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
@@ -36035,6 +36520,7 @@ function FolderRow({
|
|
|
36035
36520
|
{ type: "item", label: "Add sub-folder", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(FolderIcon, {}), onClick: onAddFolder },
|
|
36036
36521
|
{ type: "separator" },
|
|
36037
36522
|
{ type: "item", label: "Settings", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(KeyIcon, {}), onClick: () => setShowSettings(true) },
|
|
36523
|
+
{ type: "item", label: "Sync schemas", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowSchemaSync(true) },
|
|
36038
36524
|
{ type: "item", label: "Add tag", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TagIcon, {}), onClick: () => setAddingTag(true) },
|
|
36039
36525
|
{ type: "item", label: "Rename", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(PencilIcon, {}), onClick: () => setRenaming(true) },
|
|
36040
36526
|
{ type: "item", label: "Duplicate", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: onDuplicate },
|
|
@@ -36052,6 +36538,14 @@ function FolderRow({
|
|
|
36052
36538
|
folder,
|
|
36053
36539
|
onClose: () => setShowSettings(false)
|
|
36054
36540
|
}
|
|
36541
|
+
),
|
|
36542
|
+
showSchemaSync && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
36543
|
+
SchemaSyncModal,
|
|
36544
|
+
{
|
|
36545
|
+
collectionId,
|
|
36546
|
+
scope: { type: "folder", folderId: folder.id },
|
|
36547
|
+
onClose: () => setShowSchemaSync(false)
|
|
36548
|
+
}
|
|
36055
36549
|
)
|
|
36056
36550
|
] });
|
|
36057
36551
|
}
|
|
@@ -36075,14 +36569,17 @@ function FolderContents({
|
|
|
36075
36569
|
onUpdateFolderTags,
|
|
36076
36570
|
onUpdateRequestTags,
|
|
36077
36571
|
onSetRequestHookType,
|
|
36572
|
+
onToggleRequestDisabled,
|
|
36078
36573
|
onRunFolder
|
|
36079
36574
|
}) {
|
|
36080
36575
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
36081
|
-
folder.folders.map((sub) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
36576
|
+
folder.folders.map((sub, subIndex) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
36082
36577
|
FolderRow,
|
|
36083
36578
|
{
|
|
36084
36579
|
folder: sub,
|
|
36085
36580
|
collectionId,
|
|
36581
|
+
parentFolderId: folder.id,
|
|
36582
|
+
folderIndex: subIndex,
|
|
36086
36583
|
depth: depth + 1,
|
|
36087
36584
|
expandCtrl,
|
|
36088
36585
|
onAddRequest: () => onAddRequest(sub.id),
|
|
@@ -36114,6 +36611,7 @@ function FolderContents({
|
|
|
36114
36611
|
onUpdateFolderTags,
|
|
36115
36612
|
onUpdateRequestTags,
|
|
36116
36613
|
onSetRequestHookType,
|
|
36614
|
+
onToggleRequestDisabled,
|
|
36117
36615
|
onRunFolder
|
|
36118
36616
|
}
|
|
36119
36617
|
)
|
|
@@ -36132,7 +36630,9 @@ function FolderContents({
|
|
|
36132
36630
|
reqIndex,
|
|
36133
36631
|
name: req.name,
|
|
36134
36632
|
method: req.method,
|
|
36633
|
+
authType: req.auth.type,
|
|
36135
36634
|
hookType: req.hookType,
|
|
36635
|
+
disabled: req.disabled,
|
|
36136
36636
|
tags: req.meta?.tags ?? [],
|
|
36137
36637
|
isActive: req.id === activeRequestId,
|
|
36138
36638
|
autoRename: req.id === newRequestId,
|
|
@@ -36142,7 +36642,8 @@ function FolderContents({
|
|
|
36142
36642
|
onDelete: () => onDeleteRequest(req.id),
|
|
36143
36643
|
onDuplicate: () => onDuplicateRequest(req.id),
|
|
36144
36644
|
onUpdateTags: (tags2) => onUpdateRequestTags(req.id, tags2),
|
|
36145
|
-
onSetHookType: (ht) => onSetRequestHookType(req.id, ht)
|
|
36645
|
+
onSetHookType: (ht) => onSetRequestHookType(req.id, ht),
|
|
36646
|
+
onToggleDisabled: () => onToggleRequestDisabled(req.id)
|
|
36146
36647
|
},
|
|
36147
36648
|
req.id
|
|
36148
36649
|
);
|
|
@@ -36161,6 +36662,14 @@ const HOOK_COLORS = {
|
|
|
36161
36662
|
after: "bg-cyan-700 text-white",
|
|
36162
36663
|
afterAll: "bg-cyan-800 text-white"
|
|
36163
36664
|
};
|
|
36665
|
+
const AUTH_BADGE_LABELS = {
|
|
36666
|
+
basic: "Basic",
|
|
36667
|
+
bearer: "Bearer",
|
|
36668
|
+
apikey: "Key",
|
|
36669
|
+
digest: "Digest",
|
|
36670
|
+
ntlm: "NTLM",
|
|
36671
|
+
oauth2: "OAuth2"
|
|
36672
|
+
};
|
|
36164
36673
|
function RequestRow({
|
|
36165
36674
|
reqId,
|
|
36166
36675
|
collectionId,
|
|
@@ -36168,7 +36677,9 @@ function RequestRow({
|
|
|
36168
36677
|
reqIndex,
|
|
36169
36678
|
name: name2,
|
|
36170
36679
|
method,
|
|
36680
|
+
authType,
|
|
36171
36681
|
hookType,
|
|
36682
|
+
disabled,
|
|
36172
36683
|
tags: tags2,
|
|
36173
36684
|
isActive,
|
|
36174
36685
|
indent,
|
|
@@ -36178,10 +36689,12 @@ function RequestRow({
|
|
|
36178
36689
|
onDelete,
|
|
36179
36690
|
onDuplicate,
|
|
36180
36691
|
onUpdateTags,
|
|
36181
|
-
onSetHookType
|
|
36692
|
+
onSetHookType,
|
|
36693
|
+
onToggleDisabled
|
|
36182
36694
|
}) {
|
|
36183
36695
|
const [renaming, setRenaming] = reactExports.useState(autoRename);
|
|
36184
36696
|
const [addingTag, setAddingTag] = reactExports.useState(false);
|
|
36697
|
+
const [showSchemaSync, setShowSchemaSync] = reactExports.useState(false);
|
|
36185
36698
|
const [dropPos, setDropPos] = reactExports.useState(null);
|
|
36186
36699
|
const dragCtx = reactExports.useContext(DragCtx);
|
|
36187
36700
|
const hookMenuItems = [
|
|
@@ -36192,7 +36705,7 @@ function RequestRow({
|
|
|
36192
36705
|
}))
|
|
36193
36706
|
];
|
|
36194
36707
|
function handleDragOver(e) {
|
|
36195
|
-
if (!dragCtx.dragging || dragCtx.dragging.requestId === reqId) return;
|
|
36708
|
+
if (!dragCtx.dragging || dragCtx.dragging.type !== "request" || dragCtx.dragging.requestId === reqId) return;
|
|
36196
36709
|
e.preventDefault();
|
|
36197
36710
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
36198
36711
|
setDropPos(e.clientY < rect.top + rect.height / 2 ? "before" : "after");
|
|
@@ -36201,7 +36714,7 @@ function RequestRow({
|
|
|
36201
36714
|
e.preventDefault();
|
|
36202
36715
|
e.stopPropagation();
|
|
36203
36716
|
const insertIndex = dropPos === "before" ? reqIndex : reqIndex + 1;
|
|
36204
|
-
dragCtx.
|
|
36717
|
+
dragCtx.onDropRequest(collectionId, folderId, insertIndex);
|
|
36205
36718
|
setDropPos(null);
|
|
36206
36719
|
}
|
|
36207
36720
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
|
|
@@ -36210,13 +36723,13 @@ function RequestRow({
|
|
|
36210
36723
|
"div",
|
|
36211
36724
|
{
|
|
36212
36725
|
draggable: true,
|
|
36213
|
-
className: `group flex items-start gap-1.5 py-1 pr-1 rounded-sm cursor-pointer transition-colors ${isActive ? "bg-surface-800 text-[var(--text-primary)]" : "text-surface-300 hover:bg-surface-800"}`,
|
|
36726
|
+
className: `group flex items-start gap-1.5 py-1 pr-1 rounded-sm cursor-pointer transition-colors ${disabled ? "opacity-40" : ""} ${isActive ? "bg-surface-800 text-[var(--text-primary)]" : "text-surface-300 hover:bg-surface-800"}`,
|
|
36214
36727
|
style: { paddingLeft: indent },
|
|
36215
36728
|
onClick: onSelect,
|
|
36216
36729
|
onDoubleClick: () => setRenaming(true),
|
|
36217
36730
|
onDragStart: (e) => {
|
|
36218
36731
|
e.dataTransfer.effectAllowed = "move";
|
|
36219
|
-
dragCtx.setDragging({ requestId: reqId, collectionId });
|
|
36732
|
+
dragCtx.setDragging({ type: "request", requestId: reqId, collectionId });
|
|
36220
36733
|
},
|
|
36221
36734
|
onDragEnd: () => {
|
|
36222
36735
|
dragCtx.setDragging(null);
|
|
@@ -36241,7 +36754,15 @@ function RequestRow({
|
|
|
36241
36754
|
}
|
|
36242
36755
|
) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 min-w-0", children: [
|
|
36243
36756
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs truncate", children: name2 }),
|
|
36244
|
-
hookType && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `shrink-0 text-[9px] font-bold px-1 py-px rounded ${HOOK_COLORS[hookType]}`, children: HOOK_LABELS[hookType].toUpperCase() })
|
|
36757
|
+
hookType && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `shrink-0 text-[9px] font-bold px-1 py-px rounded ${HOOK_COLORS[hookType]}`, children: HOOK_LABELS[hookType].toUpperCase() }),
|
|
36758
|
+
authType !== "none" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
36759
|
+
"span",
|
|
36760
|
+
{
|
|
36761
|
+
className: "shrink-0 text-[9px] px-1 py-px rounded bg-amber-800/40 text-amber-400",
|
|
36762
|
+
title: `Auth: ${AUTH_BADGE_LABELS[authType] ?? authType}`,
|
|
36763
|
+
children: AUTH_BADGE_LABELS[authType] ?? authType
|
|
36764
|
+
}
|
|
36765
|
+
)
|
|
36245
36766
|
] }),
|
|
36246
36767
|
(tags2.length > 0 || addingTag) && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
36247
36768
|
TagChips,
|
|
@@ -36258,6 +36779,8 @@ function RequestRow({
|
|
|
36258
36779
|
{ type: "item", label: "Rename", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(PencilIcon, {}), onClick: () => setRenaming(true) },
|
|
36259
36780
|
{ type: "item", label: "Duplicate", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: onDuplicate },
|
|
36260
36781
|
{ type: "item", label: "Add tag", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TagIcon, {}), onClick: () => setAddingTag(true) },
|
|
36782
|
+
{ type: "item", label: "Sync schema", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowSchemaSync(true) },
|
|
36783
|
+
{ type: "item", label: disabled ? "Enable" : "Disable", onClick: onToggleDisabled },
|
|
36261
36784
|
{ type: "separator" },
|
|
36262
36785
|
{ type: "header", label: "Hook type" },
|
|
36263
36786
|
...hookMenuItems,
|
|
@@ -36267,6 +36790,14 @@ function RequestRow({
|
|
|
36267
36790
|
dropPos === "after" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute bottom-0 inset-x-0 h-0.5 bg-blue-500 z-10 pointer-events-none" })
|
|
36268
36791
|
]
|
|
36269
36792
|
}
|
|
36793
|
+
),
|
|
36794
|
+
showSchemaSync && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
36795
|
+
SchemaSyncModal,
|
|
36796
|
+
{
|
|
36797
|
+
collectionId,
|
|
36798
|
+
scope: { type: "request", requestId: reqId },
|
|
36799
|
+
onClose: () => setShowSchemaSync(false)
|
|
36800
|
+
}
|
|
36270
36801
|
)
|
|
36271
36802
|
] });
|
|
36272
36803
|
}
|
|
@@ -36306,48 +36837,52 @@ function ExpandAllIcon() {
|
|
|
36306
36837
|
function CollapseAllIcon() {
|
|
36307
36838
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4 6h16M4 12h8M4 18h16M21 12l-3-3-3 3" }) });
|
|
36308
36839
|
}
|
|
36840
|
+
function SyncIcon() {
|
|
36841
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182M20.984 4.356v4.993" }) });
|
|
36842
|
+
}
|
|
36309
36843
|
function GearIcon() {
|
|
36310
36844
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", children: [
|
|
36311
36845
|
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" }),
|
|
36312
36846
|
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" })
|
|
36313
36847
|
] });
|
|
36314
36848
|
}
|
|
36315
|
-
function
|
|
36316
|
-
if (root2.id ===
|
|
36849
|
+
function folderChainTo(root2, targetId) {
|
|
36850
|
+
if (root2.id === targetId) return [root2];
|
|
36317
36851
|
for (const sub of root2.folders) {
|
|
36318
|
-
const
|
|
36319
|
-
if (
|
|
36852
|
+
const chain = folderChainTo(sub, targetId);
|
|
36853
|
+
if (chain.length > 0) return [root2, ...chain];
|
|
36320
36854
|
}
|
|
36321
|
-
return
|
|
36855
|
+
return [];
|
|
36322
36856
|
}
|
|
36323
|
-
function makeHook(req, collectionVars, hookType, scopeId, scopeAncestors, mainRequestId) {
|
|
36324
|
-
return { request: req, collectionVars, isHook: true, hookType, scopeId, scopeAncestors, mainRequestId };
|
|
36857
|
+
function makeHook(req, collectionVars, hookType, scopeId, scopeAncestors, scopePath, mainRequestId) {
|
|
36858
|
+
return { request: req, collectionVars, isHook: true, hookType, scopeId, scopeAncestors, scopePath, mainRequestId };
|
|
36325
36859
|
}
|
|
36326
|
-
function buildFolderPlan(folder, requests, collectionVars, filterTags, scopeId, ancestorIds, wrappers) {
|
|
36860
|
+
function buildFolderPlan(folder, requests, collectionVars, filterTags, scopeId, ancestorIds, parentPath, wrappers, isRoot) {
|
|
36327
36861
|
const result = [];
|
|
36328
|
-
const
|
|
36862
|
+
const scopePath = isRoot ? [] : [...parentPath, folder.name];
|
|
36863
|
+
const folderReqs = folder.requestIds.map((id2) => requests[id2]).filter((r) => r && !r.disabled);
|
|
36329
36864
|
const beforeAllHooks = folderReqs.filter((r) => r.hookType === "beforeAll");
|
|
36330
36865
|
const beforeHooks = folderReqs.filter((r) => r.hookType === "before");
|
|
36331
36866
|
const afterHooks = folderReqs.filter((r) => r.hookType === "after");
|
|
36332
36867
|
const afterAllHooks = folderReqs.filter((r) => r.hookType === "afterAll");
|
|
36333
36868
|
const regularReqs = folderReqs.filter((r) => !r.hookType);
|
|
36334
|
-
const myWrapper = { scopeId, ancestors: ancestorIds, before: beforeHooks, after: afterHooks };
|
|
36869
|
+
const myWrapper = { scopeId, ancestors: ancestorIds, scopePath, before: beforeHooks, after: afterHooks };
|
|
36335
36870
|
const allWrappers = [...wrappers, myWrapper];
|
|
36336
36871
|
for (const req of beforeAllHooks) {
|
|
36337
|
-
result.push(makeHook(req, collectionVars, "beforeAll", scopeId, ancestorIds));
|
|
36872
|
+
result.push(makeHook(req, collectionVars, "beforeAll", scopeId, ancestorIds, scopePath));
|
|
36338
36873
|
}
|
|
36339
36874
|
for (const req of regularReqs) {
|
|
36340
36875
|
const tags2 = req.meta?.tags ?? [];
|
|
36341
36876
|
if (filterTags.length > 0 && !filterTags.some((t2) => tags2.includes(t2))) continue;
|
|
36342
36877
|
for (const w of allWrappers) {
|
|
36343
36878
|
for (const hookReq of w.before) {
|
|
36344
|
-
result.push(makeHook(hookReq, collectionVars, "before", w.scopeId, w.ancestors, req.id));
|
|
36879
|
+
result.push(makeHook(hookReq, collectionVars, "before", w.scopeId, w.ancestors, w.scopePath, req.id));
|
|
36345
36880
|
}
|
|
36346
36881
|
}
|
|
36347
|
-
result.push({ request: req, collectionVars, scopeId, scopeAncestors: ancestorIds });
|
|
36882
|
+
result.push({ request: req, collectionVars, scopeId, scopeAncestors: ancestorIds, scopePath });
|
|
36348
36883
|
for (const w of [...allWrappers].reverse()) {
|
|
36349
36884
|
for (const hookReq of w.after) {
|
|
36350
|
-
result.push(makeHook(hookReq, collectionVars, "after", w.scopeId, w.ancestors, req.id));
|
|
36885
|
+
result.push(makeHook(hookReq, collectionVars, "after", w.scopeId, w.ancestors, w.scopePath, req.id));
|
|
36351
36886
|
}
|
|
36352
36887
|
}
|
|
36353
36888
|
}
|
|
@@ -36361,11 +36896,13 @@ function buildFolderPlan(folder, requests, collectionVars, filterTags, scopeId,
|
|
|
36361
36896
|
effectiveFilter,
|
|
36362
36897
|
sub.id,
|
|
36363
36898
|
[...ancestorIds, scopeId],
|
|
36364
|
-
|
|
36899
|
+
scopePath,
|
|
36900
|
+
allWrappers,
|
|
36901
|
+
false
|
|
36365
36902
|
));
|
|
36366
36903
|
}
|
|
36367
36904
|
for (const req of afterAllHooks) {
|
|
36368
|
-
result.push(makeHook(req, collectionVars, "afterAll", scopeId, ancestorIds));
|
|
36905
|
+
result.push(makeHook(req, collectionVars, "afterAll", scopeId, ancestorIds, scopePath));
|
|
36369
36906
|
}
|
|
36370
36907
|
return result;
|
|
36371
36908
|
}
|
|
@@ -36394,7 +36931,7 @@ function getHooksForRequest(requestId, collection) {
|
|
|
36394
36931
|
const before = [];
|
|
36395
36932
|
const afterReversed = [];
|
|
36396
36933
|
for (const folder of path) {
|
|
36397
|
-
const reqs = folder.requestIds.map((id2) => collection.requests[id2]).filter(
|
|
36934
|
+
const reqs = folder.requestIds.map((id2) => collection.requests[id2]).filter((r) => r && !r.disabled);
|
|
36398
36935
|
const bAll = reqs.filter((r) => r.hookType === "beforeAll");
|
|
36399
36936
|
const bEach = reqs.filter((r) => r.hookType === "before");
|
|
36400
36937
|
const aEach = reqs.filter((r) => r.hookType === "after");
|
|
@@ -36406,20 +36943,65 @@ function getHooksForRequest(requestId, collection) {
|
|
|
36406
36943
|
}
|
|
36407
36944
|
function buildRunPlan(collection, folderId, filterTags) {
|
|
36408
36945
|
const collectionVars = collection.collectionVariables ?? {};
|
|
36409
|
-
if (folderId) {
|
|
36410
|
-
|
|
36411
|
-
|
|
36412
|
-
|
|
36946
|
+
if (!folderId) {
|
|
36947
|
+
return buildFolderPlan(
|
|
36948
|
+
collection.rootFolder,
|
|
36949
|
+
collection.requests,
|
|
36950
|
+
collectionVars,
|
|
36951
|
+
filterTags,
|
|
36952
|
+
collection.rootFolder.id,
|
|
36953
|
+
[],
|
|
36954
|
+
[],
|
|
36955
|
+
[],
|
|
36956
|
+
true
|
|
36957
|
+
);
|
|
36958
|
+
}
|
|
36959
|
+
const chain = folderChainTo(collection.rootFolder, folderId);
|
|
36960
|
+
if (chain.length === 0) return [];
|
|
36961
|
+
const targetFolder = chain[chain.length - 1];
|
|
36962
|
+
const ancestors = chain.slice(0, -1);
|
|
36963
|
+
const result = [];
|
|
36964
|
+
const ancestorWrappers = [];
|
|
36965
|
+
const ancestorIds = [];
|
|
36966
|
+
for (const f of ancestors) {
|
|
36967
|
+
const reqs = f.requestIds.map((id2) => collection.requests[id2]).filter((r) => r && !r.disabled);
|
|
36968
|
+
const beforeAllH = reqs.filter((r) => r.hookType === "beforeAll");
|
|
36969
|
+
const beforeH = reqs.filter((r) => r.hookType === "before");
|
|
36970
|
+
const afterH = reqs.filter((r) => r.hookType === "after");
|
|
36971
|
+
for (const req of beforeAllH) {
|
|
36972
|
+
result.push(makeHook(req, collectionVars, "beforeAll", f.id, [...ancestorIds], []));
|
|
36973
|
+
}
|
|
36974
|
+
ancestorWrappers.push({
|
|
36975
|
+
scopeId: f.id,
|
|
36976
|
+
ancestors: [...ancestorIds],
|
|
36977
|
+
scopePath: [],
|
|
36978
|
+
// ancestor hooks render with no folder heading
|
|
36979
|
+
before: beforeH,
|
|
36980
|
+
after: afterH
|
|
36981
|
+
});
|
|
36982
|
+
ancestorIds.push(f.id);
|
|
36413
36983
|
}
|
|
36414
|
-
|
|
36415
|
-
|
|
36984
|
+
result.push(...buildFolderPlan(
|
|
36985
|
+
targetFolder,
|
|
36416
36986
|
collection.requests,
|
|
36417
36987
|
collectionVars,
|
|
36418
36988
|
filterTags,
|
|
36419
|
-
|
|
36989
|
+
targetFolder.id,
|
|
36990
|
+
ancestorIds,
|
|
36420
36991
|
[],
|
|
36421
|
-
|
|
36422
|
-
|
|
36992
|
+
ancestorWrappers,
|
|
36993
|
+
true
|
|
36994
|
+
));
|
|
36995
|
+
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
36996
|
+
const f = ancestors[i];
|
|
36997
|
+
const reqs = f.requestIds.map((id2) => collection.requests[id2]).filter((r) => r && !r.disabled);
|
|
36998
|
+
const afterAllH = reqs.filter((r) => r.hookType === "afterAll");
|
|
36999
|
+
const myAncestors = ancestorIds.slice(0, i);
|
|
37000
|
+
for (const req of afterAllH) {
|
|
37001
|
+
result.push(makeHook(req, collectionVars, "afterAll", f.id, myAncestors, []));
|
|
37002
|
+
}
|
|
37003
|
+
}
|
|
37004
|
+
return result;
|
|
36423
37005
|
}
|
|
36424
37006
|
function ParamsTab({ request, onChange }) {
|
|
36425
37007
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -36428,7 +37010,8 @@ function ParamsTab({ request, onChange }) {
|
|
|
36428
37010
|
rows: request.params,
|
|
36429
37011
|
onChange: (rows) => onChange({ params: rows }),
|
|
36430
37012
|
keyPlaceholder: "param",
|
|
36431
|
-
valuePlaceholder: "value"
|
|
37013
|
+
valuePlaceholder: "value",
|
|
37014
|
+
paramMode: true
|
|
36432
37015
|
}
|
|
36433
37016
|
);
|
|
36434
37017
|
}
|
|
@@ -42332,7 +42915,7 @@ const autoCloseTags$1 = /* @__PURE__ */ EditorView.inputHandler.of((view, from,
|
|
|
42332
42915
|
]);
|
|
42333
42916
|
return true;
|
|
42334
42917
|
});
|
|
42335
|
-
const { electron: electron$
|
|
42918
|
+
const { electron: electron$m } = window;
|
|
42336
42919
|
function SoapEditor({ request, onChange }) {
|
|
42337
42920
|
const soap = request.body.soap ?? {
|
|
42338
42921
|
wsdlUrl: "",
|
|
@@ -42349,7 +42932,7 @@ function SoapEditor({ request, onChange }) {
|
|
|
42349
42932
|
setFetching(true);
|
|
42350
42933
|
setFetchError(null);
|
|
42351
42934
|
try {
|
|
42352
|
-
const result = await electron$
|
|
42935
|
+
const result = await electron$m.wsdlFetch(soap.wsdlUrl.trim());
|
|
42353
42936
|
setOperations(result.operations);
|
|
42354
42937
|
if (result.operations.length > 0) {
|
|
42355
42938
|
const first = result.operations[0];
|
|
@@ -42463,11 +43046,12 @@ function BodyTab({ request, onChange }) {
|
|
|
42463
43046
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: mode === m ? "text-white" : "text-surface-400", children: m })
|
|
42464
43047
|
] }, m)) }),
|
|
42465
43048
|
mode === "none" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-400", children: "No request body." }),
|
|
42466
|
-
mode === "json" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded overflow-hidden border border-surface-700",
|
|
43049
|
+
mode === "json" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded overflow-hidden border border-surface-700", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
42467
43050
|
ReactCodeMirror,
|
|
42468
43051
|
{
|
|
42469
43052
|
value: body.json ?? "",
|
|
42470
|
-
height: "
|
|
43053
|
+
height: "300px",
|
|
43054
|
+
maxHeight: "50vh",
|
|
42471
43055
|
theme: oneDark,
|
|
42472
43056
|
extensions: [json(), varExt],
|
|
42473
43057
|
onChange: (val) => onChange({ body: { ...body, json: val } }),
|
|
@@ -42493,11 +43077,12 @@ function BodyTab({ request, onChange }) {
|
|
|
42493
43077
|
className: "text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1 w-48 focus:outline-none focus:border-blue-500"
|
|
42494
43078
|
}
|
|
42495
43079
|
),
|
|
42496
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded overflow-hidden border border-surface-700",
|
|
43080
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded overflow-hidden border border-surface-700", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
42497
43081
|
ReactCodeMirror,
|
|
42498
43082
|
{
|
|
42499
43083
|
value: body.raw ?? "",
|
|
42500
|
-
height: "
|
|
43084
|
+
height: "300px",
|
|
43085
|
+
maxHeight: "50vh",
|
|
42501
43086
|
theme: oneDark,
|
|
42502
43087
|
extensions: [varExt],
|
|
42503
43088
|
onChange: (val) => onChange({ body: { ...body, raw: val } }),
|
|
@@ -42509,7 +43094,7 @@ function BodyTab({ request, onChange }) {
|
|
|
42509
43094
|
mode === "soap" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SoapEditor, { request, onChange }) })
|
|
42510
43095
|
] });
|
|
42511
43096
|
}
|
|
42512
|
-
const { electron: electron$
|
|
43097
|
+
const { electron: electron$l } = window;
|
|
42513
43098
|
const AUTH_TYPES = ["none", "bearer", "basic", "digest", "ntlm", "apikey", "oauth2"];
|
|
42514
43099
|
function AuthTab({ request, onChange }) {
|
|
42515
43100
|
const auth = request.auth;
|
|
@@ -42523,7 +43108,7 @@ function AuthTab({ request, onChange }) {
|
|
|
42523
43108
|
}
|
|
42524
43109
|
async function saveSecret(ref2) {
|
|
42525
43110
|
if (!secretValue || !ref2) return;
|
|
42526
|
-
await electron$
|
|
43111
|
+
await electron$l.setSecret(ref2, secretValue);
|
|
42527
43112
|
setSaved(true);
|
|
42528
43113
|
setSecretValue("");
|
|
42529
43114
|
setTimeout(() => setSaved(false), 2e3);
|
|
@@ -42534,14 +43119,14 @@ function AuthTab({ request, onChange }) {
|
|
|
42534
43119
|
try {
|
|
42535
43120
|
const vars = {};
|
|
42536
43121
|
if (auth.oauth2Flow === "authorization_code") {
|
|
42537
|
-
const result = await electron$
|
|
43122
|
+
const result = await electron$l.oauth2StartFlow(auth, vars);
|
|
42538
43123
|
setAuth({
|
|
42539
43124
|
oauth2CachedToken: result.accessToken,
|
|
42540
43125
|
oauth2TokenExpiry: result.expiresAt
|
|
42541
43126
|
});
|
|
42542
43127
|
if (result.refreshToken) setOauth2RT(result.refreshToken);
|
|
42543
43128
|
} else {
|
|
42544
|
-
const result = await electron$
|
|
43129
|
+
const result = await electron$l.oauth2StartFlow(auth, vars);
|
|
42545
43130
|
setAuth({
|
|
42546
43131
|
oauth2CachedToken: result.accessToken,
|
|
42547
43132
|
oauth2TokenExpiry: result.expiresAt
|
|
@@ -42559,7 +43144,7 @@ function AuthTab({ request, onChange }) {
|
|
|
42559
43144
|
setOauth2Status("fetching");
|
|
42560
43145
|
setOauth2Error("");
|
|
42561
43146
|
try {
|
|
42562
|
-
const result = await electron$
|
|
43147
|
+
const result = await electron$l.oauth2RefreshToken(auth, {}, oauth2RefreshToken);
|
|
42563
43148
|
setAuth({
|
|
42564
43149
|
oauth2CachedToken: result.accessToken,
|
|
42565
43150
|
oauth2TokenExpiry: result.expiresAt
|
|
@@ -50029,13 +50614,22 @@ const require$$3 = {
|
|
|
50029
50614
|
})(ajv$1, ajv$1.exports);
|
|
50030
50615
|
var ajvExports = ajv$1.exports;
|
|
50031
50616
|
const Ajv = /* @__PURE__ */ getDefaultExportFromCjs(ajvExports);
|
|
50032
|
-
const ajv = new Ajv({ allErrors: true });
|
|
50617
|
+
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
50033
50618
|
function SchemaTab({ request, onChange }) {
|
|
50034
50619
|
const activeTab = useStore((s) => s.tabs.find((t2) => t2.id === s.activeTabId));
|
|
50035
50620
|
const lastResponse = activeTab?.lastResponse ?? null;
|
|
50036
50621
|
const [result, setResult] = reactExports.useState(null);
|
|
50037
50622
|
const [error2, setError] = reactExports.useState(null);
|
|
50038
50623
|
const schemaValue = request.schema ?? "";
|
|
50624
|
+
const contractSchema = request.contract?.bodySchema ?? "";
|
|
50625
|
+
const canDerive = Boolean(contractSchema.trim());
|
|
50626
|
+
function setSchema(val) {
|
|
50627
|
+
onChange({ schema: val });
|
|
50628
|
+
}
|
|
50629
|
+
function deriveFromContract() {
|
|
50630
|
+
if (!canDerive) return;
|
|
50631
|
+
setSchema(contractSchema);
|
|
50632
|
+
}
|
|
50039
50633
|
function validate2() {
|
|
50040
50634
|
setError(null);
|
|
50041
50635
|
setResult(null);
|
|
@@ -50075,25 +50669,40 @@ function SchemaTab({ request, onChange }) {
|
|
|
50075
50669
|
setError(`Schema compile error: ${e instanceof Error ? e.message : String(e)}`);
|
|
50076
50670
|
}
|
|
50077
50671
|
}
|
|
50078
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3
|
|
50672
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
50079
50673
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
50080
50674
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-surface-600 uppercase tracking-wider font-medium", children: "JSON Schema (draft-07+)" }),
|
|
50081
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
50082
|
-
|
|
50083
|
-
|
|
50084
|
-
|
|
50085
|
-
|
|
50086
|
-
|
|
50087
|
-
|
|
50088
|
-
|
|
50675
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
50676
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50677
|
+
"button",
|
|
50678
|
+
{
|
|
50679
|
+
onClick: deriveFromContract,
|
|
50680
|
+
disabled: !canDerive,
|
|
50681
|
+
title: canDerive ? "Copy the body schema from this request's contract" : "No contract body schema defined yet",
|
|
50682
|
+
className: "px-3 py-1 text-xs bg-surface-800 hover:bg-surface-700 disabled:bg-surface-900 disabled:text-surface-600 rounded transition-colors font-medium",
|
|
50683
|
+
children: "Derive from contract"
|
|
50684
|
+
}
|
|
50685
|
+
),
|
|
50686
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50687
|
+
"button",
|
|
50688
|
+
{
|
|
50689
|
+
onClick: validate2,
|
|
50690
|
+
className: "px-3 py-1 text-xs bg-blue-700 hover:bg-blue-600 rounded transition-colors font-medium",
|
|
50691
|
+
children: "Validate"
|
|
50692
|
+
}
|
|
50693
|
+
)
|
|
50694
|
+
] })
|
|
50089
50695
|
] }),
|
|
50090
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("
|
|
50696
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-600", children: "Standalone schema for ad-hoc validation. Independent of the contract — edits here don't affect it." }),
|
|
50697
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-surface-700 rounded overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50091
50698
|
ReactCodeMirror,
|
|
50092
50699
|
{
|
|
50093
50700
|
value: schemaValue,
|
|
50701
|
+
height: "300px",
|
|
50702
|
+
maxHeight: "50vh",
|
|
50094
50703
|
theme: oneDark,
|
|
50095
50704
|
extensions: [json()],
|
|
50096
|
-
onChange: (val) =>
|
|
50705
|
+
onChange: (val) => setSchema(val),
|
|
50097
50706
|
placeholder: '{\n "type": "object",\n "properties": {}\n}',
|
|
50098
50707
|
basicSetup: { lineNumbers: true, foldGutter: true }
|
|
50099
50708
|
}
|
|
@@ -50113,7 +50722,7 @@ function SchemaTab({ request, onChange }) {
|
|
|
50113
50722
|
] }) })
|
|
50114
50723
|
] });
|
|
50115
50724
|
}
|
|
50116
|
-
const { electron: electron$
|
|
50725
|
+
const { electron: electron$k } = window;
|
|
50117
50726
|
const EMPTY = { statusCode: 200, headers: [], bodySchema: "" };
|
|
50118
50727
|
function ContractTab({ request, onChange }) {
|
|
50119
50728
|
const activeTab = useStore((s) => s.tabs.find((t2) => t2.id === s.activeTabId));
|
|
@@ -50127,7 +50736,7 @@ function ContractTab({ request, onChange }) {
|
|
|
50127
50736
|
if (!lastResponse?.body) return;
|
|
50128
50737
|
setInferring(true);
|
|
50129
50738
|
try {
|
|
50130
|
-
const schema = await electron$
|
|
50739
|
+
const schema = await electron$k.inferContractSchema(lastResponse.body);
|
|
50131
50740
|
if (schema) update({ bodySchema: schema });
|
|
50132
50741
|
} finally {
|
|
50133
50742
|
setInferring(false);
|
|
@@ -50145,7 +50754,7 @@ function ContractTab({ request, onChange }) {
|
|
|
50145
50754
|
update({ headers: (contract.headers ?? []).filter((_, idx) => idx !== i) });
|
|
50146
50755
|
}
|
|
50147
50756
|
const hasContract = contract.statusCode !== void 0 || contract.bodySchema?.trim() || contract.headers?.some((h) => h.key);
|
|
50148
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
50757
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-4 h-full min-h-0", children: [
|
|
50149
50758
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `flex items-center gap-2 px-3 py-2 rounded-lg text-xs border ${hasContract ? "bg-blue-950/40 border-blue-700 text-blue-300" : "bg-surface-800 border-surface-700 text-surface-500"}`, children: [
|
|
50150
50759
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `w-2 h-2 rounded-full ${hasContract ? "bg-blue-400" : "bg-surface-600"}` }),
|
|
50151
50760
|
hasContract ? "Contract defined — will be verified in Contract panel" : "No contract defined yet"
|
|
@@ -50221,10 +50830,12 @@ function ContractTab({ request, onChange }) {
|
|
|
50221
50830
|
}
|
|
50222
50831
|
)
|
|
50223
50832
|
] }),
|
|
50224
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-surface-700 rounded overflow-hidden",
|
|
50833
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border border-surface-700 rounded overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50225
50834
|
ReactCodeMirror,
|
|
50226
50835
|
{
|
|
50227
50836
|
value: contract.bodySchema ?? "",
|
|
50837
|
+
height: "300px",
|
|
50838
|
+
maxHeight: "50vh",
|
|
50228
50839
|
theme: oneDark,
|
|
50229
50840
|
extensions: [json()],
|
|
50230
50841
|
onChange: (val) => update({ bodySchema: val }),
|
|
@@ -50235,7 +50846,7 @@ function ContractTab({ request, onChange }) {
|
|
|
50235
50846
|
] })
|
|
50236
50847
|
] });
|
|
50237
50848
|
}
|
|
50238
|
-
const { electron: electron$
|
|
50849
|
+
const { electron: electron$j } = window;
|
|
50239
50850
|
function formatTime$1(ts) {
|
|
50240
50851
|
const d = new Date(ts);
|
|
50241
50852
|
const hh = String(d.getHours()).padStart(2, "0");
|
|
@@ -50255,14 +50866,14 @@ function WebSocketPanel({ request }) {
|
|
|
50255
50866
|
const [sendText, setSendText] = reactExports.useState("");
|
|
50256
50867
|
const logEndRef = reactExports.useRef(null);
|
|
50257
50868
|
reactExports.useEffect(() => {
|
|
50258
|
-
electron$
|
|
50869
|
+
electron$j.onWsMessage(({ requestId, message }) => {
|
|
50259
50870
|
addWsMessage(requestId, message);
|
|
50260
50871
|
});
|
|
50261
|
-
electron$
|
|
50872
|
+
electron$j.onWsStatus(({ requestId, status, error: error2 }) => {
|
|
50262
50873
|
setWsStatus(requestId, status, error2);
|
|
50263
50874
|
});
|
|
50264
50875
|
return () => {
|
|
50265
|
-
electron$
|
|
50876
|
+
electron$j.offWsEvents();
|
|
50266
50877
|
};
|
|
50267
50878
|
}, [addWsMessage, setWsStatus]);
|
|
50268
50879
|
reactExports.useEffect(() => {
|
|
@@ -50275,19 +50886,19 @@ function WebSocketPanel({ request }) {
|
|
|
50275
50886
|
if (h.enabled && h.key) headers[h.key] = h.value;
|
|
50276
50887
|
}
|
|
50277
50888
|
try {
|
|
50278
|
-
await electron$
|
|
50889
|
+
await electron$j.wsConnect(request.id, request.url, headers);
|
|
50279
50890
|
} catch (err) {
|
|
50280
50891
|
setWsStatus(request.id, "error", err instanceof Error ? err.message : String(err));
|
|
50281
50892
|
}
|
|
50282
50893
|
}
|
|
50283
50894
|
async function disconnect() {
|
|
50284
|
-
await electron$
|
|
50895
|
+
await electron$j.wsDisconnect(request.id);
|
|
50285
50896
|
}
|
|
50286
50897
|
async function sendMessage() {
|
|
50287
50898
|
const text = sendText.trim();
|
|
50288
50899
|
if (!text || !isConnected) return;
|
|
50289
50900
|
try {
|
|
50290
|
-
await electron$
|
|
50901
|
+
await electron$j.wsSend(request.id, text);
|
|
50291
50902
|
const msg = {
|
|
50292
50903
|
id: crypto.randomUUID(),
|
|
50293
50904
|
direction: "sent",
|
|
@@ -50390,7 +51001,7 @@ function WebSocketPanel({ request }) {
|
|
|
50390
51001
|
] })
|
|
50391
51002
|
] });
|
|
50392
51003
|
}
|
|
50393
|
-
const { electron: electron$
|
|
51004
|
+
const { electron: electron$i } = window;
|
|
50394
51005
|
const METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
50395
51006
|
const METHOD_COLORS = {
|
|
50396
51007
|
GET: "text-emerald-400",
|
|
@@ -50401,6 +51012,13 @@ const METHOD_COLORS = {
|
|
|
50401
51012
|
HEAD: "text-purple-400",
|
|
50402
51013
|
OPTIONS: "text-gray-400"
|
|
50403
51014
|
};
|
|
51015
|
+
function deriveHookStatus(r) {
|
|
51016
|
+
if (r.scriptResult.postScriptError) return "error";
|
|
51017
|
+
if (r.response.status >= 400) return "failed";
|
|
51018
|
+
const tests = r.scriptResult.testResults;
|
|
51019
|
+
if (tests.length === 0) return "skipped";
|
|
51020
|
+
return tests.every((t2) => t2.passed) ? "passed" : "failed";
|
|
51021
|
+
}
|
|
50404
51022
|
function RequestBuilder({ request }) {
|
|
50405
51023
|
const updateRequest = useStore((s) => s.updateRequest);
|
|
50406
51024
|
const activeEnvironmentId = useStore((s) => s.activeEnvironmentId);
|
|
@@ -50468,17 +51086,24 @@ function RequestBuilder({ request }) {
|
|
|
50468
51086
|
for (const hook of hooks.before) {
|
|
50469
51087
|
const start = Date.now();
|
|
50470
51088
|
try {
|
|
50471
|
-
const
|
|
51089
|
+
const hookEnv = activeEnvironmentId ? useStore.getState().environments[activeEnvironmentId]?.data ?? null : null;
|
|
51090
|
+
const hookSessionVars = useStore.getState().sessionVars;
|
|
51091
|
+
const r = await electron$i.sendRequest({
|
|
51092
|
+
...basePayload,
|
|
51093
|
+
environment: hookEnv,
|
|
51094
|
+
request: hook,
|
|
51095
|
+
collectionVars: { ...collectionVars, ...hookSessionVars },
|
|
51096
|
+
globals: liveGlobals
|
|
51097
|
+
});
|
|
50472
51098
|
applyScriptUpdates(r.scriptResult);
|
|
50473
51099
|
collectionVars = { ...collectionVars, ...r.scriptResult.updatedCollectionVars };
|
|
50474
51100
|
liveGlobals = { ...liveGlobals, ...r.scriptResult.updatedGlobals };
|
|
50475
|
-
const allPassed = r.scriptResult.testResults.every((t2) => t2.passed);
|
|
50476
51101
|
collectedHookResults.push({
|
|
50477
51102
|
requestId: hook.id,
|
|
50478
51103
|
name: hook.name,
|
|
50479
51104
|
method: hook.method,
|
|
50480
51105
|
resolvedUrl: r.scriptResult.resolvedUrl,
|
|
50481
|
-
status: r
|
|
51106
|
+
status: deriveHookStatus(r),
|
|
50482
51107
|
httpStatus: r.response.status,
|
|
50483
51108
|
durationMs: Date.now() - start,
|
|
50484
51109
|
isHook: true,
|
|
@@ -50502,10 +51127,13 @@ function RequestBuilder({ request }) {
|
|
|
50502
51127
|
});
|
|
50503
51128
|
}
|
|
50504
51129
|
}
|
|
50505
|
-
const
|
|
51130
|
+
const freshEnv = activeEnvironmentId ? useStore.getState().environments[activeEnvironmentId]?.data ?? null : null;
|
|
51131
|
+
const freshSessionVars = useStore.getState().sessionVars;
|
|
51132
|
+
const result = await electron$i.sendRequest({
|
|
50506
51133
|
...basePayload,
|
|
51134
|
+
environment: freshEnv,
|
|
50507
51135
|
request: mergedRequest,
|
|
50508
|
-
collectionVars,
|
|
51136
|
+
collectionVars: { ...collectionVars, ...freshSessionVars },
|
|
50509
51137
|
globals: liveGlobals
|
|
50510
51138
|
});
|
|
50511
51139
|
setTabResponse(activeTabId, result.response, result.scriptResult, result.sentRequest);
|
|
@@ -50524,17 +51152,24 @@ function RequestBuilder({ request }) {
|
|
|
50524
51152
|
for (const hook of hooks.after) {
|
|
50525
51153
|
const start = Date.now();
|
|
50526
51154
|
try {
|
|
50527
|
-
const
|
|
51155
|
+
const hookEnv = activeEnvironmentId ? useStore.getState().environments[activeEnvironmentId]?.data ?? null : null;
|
|
51156
|
+
const hookSessionVars = useStore.getState().sessionVars;
|
|
51157
|
+
const r = await electron$i.sendRequest({
|
|
51158
|
+
...basePayload,
|
|
51159
|
+
environment: hookEnv,
|
|
51160
|
+
request: hook,
|
|
51161
|
+
collectionVars: { ...collectionVars, ...hookSessionVars },
|
|
51162
|
+
globals: liveGlobals
|
|
51163
|
+
});
|
|
50528
51164
|
applyScriptUpdates(r.scriptResult);
|
|
50529
51165
|
collectionVars = { ...collectionVars, ...r.scriptResult.updatedCollectionVars };
|
|
50530
51166
|
liveGlobals = { ...liveGlobals, ...r.scriptResult.updatedGlobals };
|
|
50531
|
-
const allPassed = r.scriptResult.testResults.every((t2) => t2.passed);
|
|
50532
51167
|
collectedHookResults.push({
|
|
50533
51168
|
requestId: hook.id,
|
|
50534
51169
|
name: hook.name,
|
|
50535
51170
|
method: hook.method,
|
|
50536
51171
|
resolvedUrl: r.scriptResult.resolvedUrl,
|
|
50537
|
-
status: r
|
|
51172
|
+
status: deriveHookStatus(r),
|
|
50538
51173
|
httpStatus: r.response.status,
|
|
50539
51174
|
durationMs: Date.now() - start,
|
|
50540
51175
|
isHook: true,
|
|
@@ -50672,28 +51307,136 @@ function RequestBuilder({ request }) {
|
|
|
50672
51307
|
},
|
|
50673
51308
|
tab.id
|
|
50674
51309
|
)) }),
|
|
50675
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
50676
|
-
"
|
|
51310
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3 flex-1 overflow-y-auto min-h-0", children: [
|
|
51311
|
+
activeTab === "params" && /* @__PURE__ */ jsxRuntimeExports.jsx(ParamsTab, { request, onChange: update }),
|
|
51312
|
+
activeTab === "headers" && /* @__PURE__ */ jsxRuntimeExports.jsx(HeadersTab, { request, onChange: update }),
|
|
51313
|
+
activeTab === "body" && /* @__PURE__ */ jsxRuntimeExports.jsx(BodyTab, { request, onChange: update }),
|
|
51314
|
+
activeTab === "auth" && /* @__PURE__ */ jsxRuntimeExports.jsx(AuthTab, { request, onChange: update }),
|
|
51315
|
+
activeTab === "scripts" && /* @__PURE__ */ jsxRuntimeExports.jsx(ScriptsTab, { request, onChange: update }),
|
|
51316
|
+
activeTab === "schema" && /* @__PURE__ */ jsxRuntimeExports.jsx(SchemaTab, { request, onChange: update }),
|
|
51317
|
+
activeTab === "contract" && /* @__PURE__ */ jsxRuntimeExports.jsx(ContractTab, { request, onChange: update })
|
|
51318
|
+
] })
|
|
51319
|
+
] })
|
|
51320
|
+
] });
|
|
51321
|
+
}
|
|
51322
|
+
function JsonNode({ nodeKey, value, path, depth, onLeaf }) {
|
|
51323
|
+
const [expanded, setExpanded] = reactExports.useState(depth < 2);
|
|
51324
|
+
const keySpan = nodeKey !== null ? /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-500 font-mono text-xs shrink-0 select-all", children: [
|
|
51325
|
+
typeof nodeKey === "number" ? `[${nodeKey}]` : nodeKey,
|
|
51326
|
+
value === null || typeof value !== "object" ? ":" : ""
|
|
51327
|
+
] }) : null;
|
|
51328
|
+
if (value === null || typeof value !== "object") {
|
|
51329
|
+
const display = value === null ? "null" : typeof value === "string" ? `"${value.length > 100 ? value.slice(0, 100) + "…" : value}"` : String(value);
|
|
51330
|
+
const cls = value === null ? "text-surface-600 italic" : typeof value === "string" ? "text-emerald-400" : typeof value === "number" ? "text-blue-400" : "text-amber-400";
|
|
51331
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "group flex items-center gap-1.5 py-0.5 pl-1 rounded hover:bg-surface-800/40 min-w-0", children: [
|
|
51332
|
+
keySpan,
|
|
51333
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `font-mono text-xs ${cls} select-all break-all min-w-0 truncate`, children: display }),
|
|
51334
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
51335
|
+
"button",
|
|
50677
51336
|
{
|
|
50678
|
-
|
|
50679
|
-
|
|
50680
|
-
|
|
50681
|
-
|
|
50682
|
-
activeTab === "headers" && /* @__PURE__ */ jsxRuntimeExports.jsx(HeadersTab, { request, onChange: update }),
|
|
50683
|
-
activeTab === "body" && /* @__PURE__ */ jsxRuntimeExports.jsx(BodyTab, { request, onChange: update }),
|
|
50684
|
-
activeTab === "auth" && /* @__PURE__ */ jsxRuntimeExports.jsx(AuthTab, { request, onChange: update }),
|
|
50685
|
-
activeTab === "scripts" && /* @__PURE__ */ jsxRuntimeExports.jsx(ScriptsTab, { request, onChange: update }),
|
|
50686
|
-
activeTab === "schema" && /* @__PURE__ */ jsxRuntimeExports.jsx(SchemaTab, { request, onChange: update }),
|
|
50687
|
-
activeTab === "contract" && /* @__PURE__ */ jsxRuntimeExports.jsx(ContractTab, { request, onChange: update })
|
|
50688
|
-
]
|
|
51337
|
+
onClick: (e) => onLeaf(e, path, value),
|
|
51338
|
+
className: "ml-auto opacity-0 group-hover:opacity-100 shrink-0 text-[10px] px-1.5 leading-4 py-0.5 text-blue-400 border border-blue-800 hover:border-blue-500 hover:text-blue-300 rounded transition-all",
|
|
51339
|
+
title: "Add assertion for this value",
|
|
51340
|
+
children: "+ insert"
|
|
50689
51341
|
}
|
|
50690
51342
|
)
|
|
50691
|
-
] })
|
|
51343
|
+
] });
|
|
51344
|
+
}
|
|
51345
|
+
const isArr = Array.isArray(value);
|
|
51346
|
+
const entries = isArr ? value.map((v, i) => [i, v]) : Object.entries(value);
|
|
51347
|
+
const summary = isArr ? `[${value.length}]` : `{${entries.length}}`;
|
|
51348
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
51349
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
51350
|
+
"button",
|
|
51351
|
+
{
|
|
51352
|
+
onClick: () => setExpanded((v) => !v),
|
|
51353
|
+
className: "flex items-center gap-1.5 py-0.5 pl-1 rounded hover:bg-surface-800/40 w-full text-left",
|
|
51354
|
+
children: [
|
|
51355
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-[10px] w-3 shrink-0 text-center", children: expanded ? "▾" : "▸" }),
|
|
51356
|
+
keySpan,
|
|
51357
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-xs", children: summary })
|
|
51358
|
+
]
|
|
51359
|
+
}
|
|
51360
|
+
),
|
|
51361
|
+
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-4 border-l border-surface-800 pl-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
51362
|
+
JsonNode,
|
|
51363
|
+
{
|
|
51364
|
+
nodeKey: k,
|
|
51365
|
+
value: v,
|
|
51366
|
+
path: [...path, k],
|
|
51367
|
+
depth: depth + 1,
|
|
51368
|
+
onLeaf
|
|
51369
|
+
},
|
|
51370
|
+
String(k)
|
|
51371
|
+
)) })
|
|
51372
|
+
] });
|
|
51373
|
+
}
|
|
51374
|
+
function buildSelector(el) {
|
|
51375
|
+
const parts = [];
|
|
51376
|
+
let cur2 = el;
|
|
51377
|
+
while (cur2) {
|
|
51378
|
+
const parent = cur2.parentElement;
|
|
51379
|
+
if (!parent) break;
|
|
51380
|
+
const tag = cur2.tagName;
|
|
51381
|
+
const siblings = Array.from(parent.children).filter((c) => c.tagName === tag);
|
|
51382
|
+
parts.unshift(siblings.length > 1 ? `${tag}:nth-of-type(${siblings.indexOf(cur2) + 1})` : tag);
|
|
51383
|
+
cur2 = parent;
|
|
51384
|
+
}
|
|
51385
|
+
return parts.join(" > ");
|
|
51386
|
+
}
|
|
51387
|
+
function XmlNode({ element, depth, onLeaf }) {
|
|
51388
|
+
const [expanded, setExpanded] = reactExports.useState(depth < 3);
|
|
51389
|
+
const childEls = Array.from(element.children);
|
|
51390
|
+
const tag = element.tagName;
|
|
51391
|
+
if (childEls.length === 0) {
|
|
51392
|
+
const text = element.textContent ?? "";
|
|
51393
|
+
const selector = buildSelector(element);
|
|
51394
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "group flex items-center gap-1.5 py-0.5 pl-1 rounded hover:bg-surface-800/40 min-w-0", children: [
|
|
51395
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-300 font-mono text-xs shrink-0", children: [
|
|
51396
|
+
"<",
|
|
51397
|
+
tag,
|
|
51398
|
+
">"
|
|
51399
|
+
] }),
|
|
51400
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400 font-mono text-xs select-all break-all min-w-0 truncate", children: text.length > 100 ? text.slice(0, 100) + "…" : text }),
|
|
51401
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
51402
|
+
"button",
|
|
51403
|
+
{
|
|
51404
|
+
onClick: (e) => onLeaf(e, selector, text),
|
|
51405
|
+
className: "ml-auto opacity-0 group-hover:opacity-100 shrink-0 text-[10px] px-1.5 leading-4 py-0.5 text-blue-400 border border-blue-800 hover:border-blue-500 hover:text-blue-300 rounded transition-all",
|
|
51406
|
+
title: "Add assertion for this value",
|
|
51407
|
+
children: "+ insert"
|
|
51408
|
+
}
|
|
51409
|
+
)
|
|
51410
|
+
] });
|
|
51411
|
+
}
|
|
51412
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
51413
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
51414
|
+
"button",
|
|
51415
|
+
{
|
|
51416
|
+
onClick: () => setExpanded((v) => !v),
|
|
51417
|
+
className: "flex items-center gap-1.5 py-0.5 pl-1 rounded hover:bg-surface-800/40 w-full text-left",
|
|
51418
|
+
children: [
|
|
51419
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-[10px] w-3 shrink-0 text-center", children: expanded ? "▾" : "▸" }),
|
|
51420
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-300 font-mono text-xs", children: [
|
|
51421
|
+
"<",
|
|
51422
|
+
tag,
|
|
51423
|
+
">"
|
|
51424
|
+
] }),
|
|
51425
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-xs ml-1", children: childEls.length })
|
|
51426
|
+
]
|
|
51427
|
+
}
|
|
51428
|
+
),
|
|
51429
|
+
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-4 border-l border-surface-800 pl-1", children: childEls.map((child, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(XmlNode, { element: child, depth: depth + 1, onLeaf }, i)) })
|
|
50692
51430
|
] });
|
|
50693
51431
|
}
|
|
50694
51432
|
function esc(s) {
|
|
50695
51433
|
return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "");
|
|
50696
51434
|
}
|
|
51435
|
+
function toLit(v) {
|
|
51436
|
+
if (v === null) return "null";
|
|
51437
|
+
if (typeof v === "string") return `"${esc(v)}"`;
|
|
51438
|
+
return String(v);
|
|
51439
|
+
}
|
|
50697
51440
|
function jsonAccessor(path) {
|
|
50698
51441
|
return path.reduce((acc, key) => {
|
|
50699
51442
|
if (typeof key === "number") return `${acc}[${key}]`;
|
|
@@ -50704,10 +51447,32 @@ function jsonPathLabel(path) {
|
|
|
50704
51447
|
if (path.length === 0) return "$";
|
|
50705
51448
|
return path.map((k) => typeof k === "number" ? `[${k}]` : k).join(".");
|
|
50706
51449
|
}
|
|
50707
|
-
function
|
|
50708
|
-
|
|
50709
|
-
|
|
50710
|
-
|
|
51450
|
+
function getAtPath(root2, path) {
|
|
51451
|
+
let cur2 = root2;
|
|
51452
|
+
for (const key of path) {
|
|
51453
|
+
if (cur2 == null || typeof cur2 !== "object") return void 0;
|
|
51454
|
+
cur2 = cur2[key];
|
|
51455
|
+
}
|
|
51456
|
+
return cur2;
|
|
51457
|
+
}
|
|
51458
|
+
function toJsonPathExpr(path, filterKey, filterValue) {
|
|
51459
|
+
let arrayIdx = -1;
|
|
51460
|
+
for (let i = path.length - 1; i >= 0; i--) {
|
|
51461
|
+
if (typeof path[i] === "number") {
|
|
51462
|
+
arrayIdx = i;
|
|
51463
|
+
break;
|
|
51464
|
+
}
|
|
51465
|
+
}
|
|
51466
|
+
if (arrayIdx < 0) return "";
|
|
51467
|
+
const prefix2 = path.slice(0, arrayIdx).join(".");
|
|
51468
|
+
const arrayPart = prefix2 ? "$." + prefix2 : "$";
|
|
51469
|
+
const leafPart = path.slice(arrayIdx + 1).join(".");
|
|
51470
|
+
const filterVal = isNaN(Number(filterValue)) ? `"${filterValue.replace(/"/g, '\\"')}"` : filterValue;
|
|
51471
|
+
return leafPart ? `${arrayPart}[?(@.${filterKey}==${filterVal})].${leafPart}` : `${arrayPart}[?(@.${filterKey}==${filterVal})]`;
|
|
51472
|
+
}
|
|
51473
|
+
function varNameFromPath(path) {
|
|
51474
|
+
const stringSegments = path.filter((k) => typeof k === "string");
|
|
51475
|
+
return stringSegments[stringSegments.length - 1] ?? "extracted_value";
|
|
50711
51476
|
}
|
|
50712
51477
|
function makeJsonSnippet(path, value, mode) {
|
|
50713
51478
|
const acc = jsonAccessor(path);
|
|
@@ -50739,29 +51504,6 @@ function makeJsonSnippet(path, value, mode) {
|
|
|
50739
51504
|
});`;
|
|
50740
51505
|
}
|
|
50741
51506
|
}
|
|
50742
|
-
function getAtPath(root2, path) {
|
|
50743
|
-
let cur2 = root2;
|
|
50744
|
-
for (const key of path) {
|
|
50745
|
-
if (cur2 == null || typeof cur2 !== "object") return void 0;
|
|
50746
|
-
cur2 = cur2[key];
|
|
50747
|
-
}
|
|
50748
|
-
return cur2;
|
|
50749
|
-
}
|
|
50750
|
-
function toJsonPathExpr(path, filterKey, filterValue) {
|
|
50751
|
-
let arrayIdx = -1;
|
|
50752
|
-
for (let i = path.length - 1; i >= 0; i--) {
|
|
50753
|
-
if (typeof path[i] === "number") {
|
|
50754
|
-
arrayIdx = i;
|
|
50755
|
-
break;
|
|
50756
|
-
}
|
|
50757
|
-
}
|
|
50758
|
-
if (arrayIdx < 0) return "";
|
|
50759
|
-
const arrayPart = "$." + path.slice(0, arrayIdx).join(".");
|
|
50760
|
-
const leafPart = path.slice(arrayIdx + 1).join(".");
|
|
50761
|
-
const filterVal = isNaN(Number(filterValue)) ? `"${filterValue.replace(/"/g, '\\"')}"` : filterValue;
|
|
50762
|
-
const expr = leafPart ? `${arrayPart}[?(@.${filterKey}==${filterVal})].${leafPart}` : `${arrayPart}[?(@.${filterKey}==${filterVal})]`;
|
|
50763
|
-
return expr;
|
|
50764
|
-
}
|
|
50765
51507
|
function makeJsonPathSnippet(path, value, filterKey, filterValue) {
|
|
50766
51508
|
const expr = toJsonPathExpr(path, filterKey, filterValue);
|
|
50767
51509
|
const lit = toLit(value);
|
|
@@ -50788,9 +51530,6 @@ function makeXmlSnippet(selector, value, mode) {
|
|
|
50788
51530
|
});`;
|
|
50789
51531
|
}
|
|
50790
51532
|
}
|
|
50791
|
-
function varNameFromPath(path) {
|
|
50792
|
-
return path.filter((k) => typeof k === "string").at(-1) ?? "extracted_value";
|
|
50793
|
-
}
|
|
50794
51533
|
function makeJsonExtractSnippet(path, target) {
|
|
50795
51534
|
const acc = jsonAccessor(path);
|
|
50796
51535
|
const varName = varNameFromPath(path);
|
|
@@ -50806,11 +51545,7 @@ sp.${target}.set("${varName}", String(matches[0] ?? ''));`;
|
|
|
50806
51545
|
function makeXmlExtractSnippet(selector, target) {
|
|
50807
51546
|
return `sp.${target}.set("extracted_value", sp.response.xmlText("${selector.replace(/"/g, '\\"')}") ?? '');`;
|
|
50808
51547
|
}
|
|
50809
|
-
function AssertMenu({
|
|
50810
|
-
state,
|
|
50811
|
-
onClose,
|
|
50812
|
-
onConfirm
|
|
50813
|
-
}) {
|
|
51548
|
+
function AssertMenu({ state, onClose, onConfirm }) {
|
|
50814
51549
|
const ref2 = reactExports.useRef(null);
|
|
50815
51550
|
const [jpOpen, setJpOpen] = reactExports.useState(false);
|
|
50816
51551
|
const [filterKey, setFilterKey] = reactExports.useState("");
|
|
@@ -51034,126 +51769,6 @@ function AssertMenu({
|
|
|
51034
51769
|
}
|
|
51035
51770
|
);
|
|
51036
51771
|
}
|
|
51037
|
-
function JsonNode({
|
|
51038
|
-
nodeKey,
|
|
51039
|
-
value,
|
|
51040
|
-
path,
|
|
51041
|
-
depth,
|
|
51042
|
-
onLeaf
|
|
51043
|
-
}) {
|
|
51044
|
-
const [expanded, setExpanded] = reactExports.useState(depth < 2);
|
|
51045
|
-
const keySpan = nodeKey !== null ? /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-500 font-mono text-xs shrink-0 select-all", children: [
|
|
51046
|
-
typeof nodeKey === "number" ? `[${nodeKey}]` : nodeKey,
|
|
51047
|
-
value === null || typeof value !== "object" ? ":" : ""
|
|
51048
|
-
] }) : null;
|
|
51049
|
-
if (value === null || typeof value !== "object") {
|
|
51050
|
-
const display = value === null ? "null" : typeof value === "string" ? `"${value.length > 100 ? value.slice(0, 100) + "…" : value}"` : String(value);
|
|
51051
|
-
const cls = value === null ? "text-surface-600 italic" : typeof value === "string" ? "text-emerald-400" : typeof value === "number" ? "text-blue-400" : "text-amber-400";
|
|
51052
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "group flex items-center gap-1.5 py-0.5 pl-1 rounded hover:bg-surface-800/40 min-w-0", children: [
|
|
51053
|
-
keySpan,
|
|
51054
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `font-mono text-xs ${cls} select-all break-all min-w-0 truncate`, children: display }),
|
|
51055
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
51056
|
-
"button",
|
|
51057
|
-
{
|
|
51058
|
-
onClick: (e) => onLeaf(e, path, value),
|
|
51059
|
-
className: "ml-auto opacity-0 group-hover:opacity-100 shrink-0 text-[10px] px-1.5 leading-4 py-0.5 text-blue-400 border border-blue-800 hover:border-blue-500 hover:text-blue-300 rounded transition-all",
|
|
51060
|
-
title: "Add assertion for this value",
|
|
51061
|
-
children: "+ insert"
|
|
51062
|
-
}
|
|
51063
|
-
)
|
|
51064
|
-
] });
|
|
51065
|
-
}
|
|
51066
|
-
const isArr = Array.isArray(value);
|
|
51067
|
-
const entries = isArr ? value.map((v, i) => [i, v]) : Object.entries(value);
|
|
51068
|
-
const summary = isArr ? `[${value.length}]` : `{${entries.length}}`;
|
|
51069
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
51070
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
51071
|
-
"button",
|
|
51072
|
-
{
|
|
51073
|
-
onClick: () => setExpanded((v) => !v),
|
|
51074
|
-
className: "flex items-center gap-1.5 py-0.5 pl-1 rounded hover:bg-surface-800/40 w-full text-left",
|
|
51075
|
-
children: [
|
|
51076
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-[10px] w-3 shrink-0 text-center", children: expanded ? "▾" : "▸" }),
|
|
51077
|
-
keySpan,
|
|
51078
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-xs", children: summary })
|
|
51079
|
-
]
|
|
51080
|
-
}
|
|
51081
|
-
),
|
|
51082
|
-
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-4 border-l border-surface-800 pl-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
51083
|
-
JsonNode,
|
|
51084
|
-
{
|
|
51085
|
-
nodeKey: k,
|
|
51086
|
-
value: v,
|
|
51087
|
-
path: [...path, k],
|
|
51088
|
-
depth: depth + 1,
|
|
51089
|
-
onLeaf
|
|
51090
|
-
},
|
|
51091
|
-
String(k)
|
|
51092
|
-
)) })
|
|
51093
|
-
] });
|
|
51094
|
-
}
|
|
51095
|
-
function buildSelector(el) {
|
|
51096
|
-
const parts = [];
|
|
51097
|
-
let cur2 = el;
|
|
51098
|
-
while (cur2) {
|
|
51099
|
-
const parent = cur2.parentElement;
|
|
51100
|
-
if (!parent) break;
|
|
51101
|
-
const tag = cur2.tagName;
|
|
51102
|
-
const siblings = Array.from(parent.children).filter((c) => c.tagName === tag);
|
|
51103
|
-
parts.unshift(siblings.length > 1 ? `${tag}:nth-of-type(${siblings.indexOf(cur2) + 1})` : tag);
|
|
51104
|
-
cur2 = parent;
|
|
51105
|
-
}
|
|
51106
|
-
return parts.join(" > ");
|
|
51107
|
-
}
|
|
51108
|
-
function XmlNode({
|
|
51109
|
-
element,
|
|
51110
|
-
depth,
|
|
51111
|
-
onLeaf
|
|
51112
|
-
}) {
|
|
51113
|
-
const [expanded, setExpanded] = reactExports.useState(depth < 3);
|
|
51114
|
-
const childEls = Array.from(element.children);
|
|
51115
|
-
const tag = element.tagName;
|
|
51116
|
-
if (childEls.length === 0) {
|
|
51117
|
-
const text = element.textContent ?? "";
|
|
51118
|
-
const selector = buildSelector(element);
|
|
51119
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "group flex items-center gap-1.5 py-0.5 pl-1 rounded hover:bg-surface-800/40 min-w-0", children: [
|
|
51120
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-300 font-mono text-xs shrink-0", children: [
|
|
51121
|
-
"<",
|
|
51122
|
-
tag,
|
|
51123
|
-
">"
|
|
51124
|
-
] }),
|
|
51125
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400 font-mono text-xs select-all break-all min-w-0 truncate", children: text.length > 100 ? text.slice(0, 100) + "…" : text }),
|
|
51126
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
51127
|
-
"button",
|
|
51128
|
-
{
|
|
51129
|
-
onClick: (e) => onLeaf(e, selector, text),
|
|
51130
|
-
className: "ml-auto opacity-0 group-hover:opacity-100 shrink-0 text-[10px] px-1.5 leading-4 py-0.5 text-blue-400 border border-blue-800 hover:border-blue-500 hover:text-blue-300 rounded transition-all",
|
|
51131
|
-
title: "Add assertion for this value",
|
|
51132
|
-
children: "+ insert"
|
|
51133
|
-
}
|
|
51134
|
-
)
|
|
51135
|
-
] });
|
|
51136
|
-
}
|
|
51137
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
51138
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
51139
|
-
"button",
|
|
51140
|
-
{
|
|
51141
|
-
onClick: () => setExpanded((v) => !v),
|
|
51142
|
-
className: "flex items-center gap-1.5 py-0.5 pl-1 rounded hover:bg-surface-800/40 w-full text-left",
|
|
51143
|
-
children: [
|
|
51144
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-[10px] w-3 shrink-0 text-center", children: expanded ? "▾" : "▸" }),
|
|
51145
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-blue-300 font-mono text-xs", children: [
|
|
51146
|
-
"<",
|
|
51147
|
-
tag,
|
|
51148
|
-
">"
|
|
51149
|
-
] }),
|
|
51150
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-xs ml-1", children: childEls.length })
|
|
51151
|
-
]
|
|
51152
|
-
}
|
|
51153
|
-
),
|
|
51154
|
-
expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-4 border-l border-surface-800 pl-1", children: childEls.map((child, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(XmlNode, { element: child, depth: depth + 1, onLeaf }, i)) })
|
|
51155
|
-
] });
|
|
51156
|
-
}
|
|
51157
51772
|
function InteractiveBody({ body, contentType, onAssert }) {
|
|
51158
51773
|
const [popover, setPopover] = reactExports.useState(null);
|
|
51159
51774
|
const isJson = contentType.includes("json");
|
|
@@ -51201,40 +51816,6 @@ function InteractiveBody({ body, contentType, onAssert }) {
|
|
|
51201
51816
|
treeContent
|
|
51202
51817
|
] });
|
|
51203
51818
|
}
|
|
51204
|
-
const { electron: electron$g } = window;
|
|
51205
|
-
function prettyJson(raw) {
|
|
51206
|
-
try {
|
|
51207
|
-
return JSON.stringify(JSON.parse(raw), null, 2);
|
|
51208
|
-
} catch {
|
|
51209
|
-
return raw;
|
|
51210
|
-
}
|
|
51211
|
-
}
|
|
51212
|
-
function prettyXml(raw) {
|
|
51213
|
-
try {
|
|
51214
|
-
const indent = " ";
|
|
51215
|
-
let result = "";
|
|
51216
|
-
let depth = 0;
|
|
51217
|
-
const tokens = raw.match(/<[^>]+>|[^<]+/g) ?? [];
|
|
51218
|
-
for (const token of tokens) {
|
|
51219
|
-
const text = token.trim();
|
|
51220
|
-
if (!text) continue;
|
|
51221
|
-
if (text.startsWith("<?") || text.startsWith("<!")) {
|
|
51222
|
-
result += indent.repeat(depth) + text + "\n";
|
|
51223
|
-
} else if (token.startsWith("</")) {
|
|
51224
|
-
depth = Math.max(0, depth - 1);
|
|
51225
|
-
result += indent.repeat(depth) + text + "\n";
|
|
51226
|
-
} else if (token.startsWith("<") && !token.endsWith("/>") && !token.includes("</")) {
|
|
51227
|
-
result += indent.repeat(depth) + text + "\n";
|
|
51228
|
-
depth++;
|
|
51229
|
-
} else {
|
|
51230
|
-
result += indent.repeat(depth) + text + "\n";
|
|
51231
|
-
}
|
|
51232
|
-
}
|
|
51233
|
-
return result.trimEnd();
|
|
51234
|
-
} catch {
|
|
51235
|
-
return raw;
|
|
51236
|
-
}
|
|
51237
|
-
}
|
|
51238
51819
|
const HOOK_BADGE$1 = {
|
|
51239
51820
|
beforeAll: { label: "BEFORE ALL", cls: "bg-violet-700 text-white" },
|
|
51240
51821
|
before: { label: "BEFORE", cls: "bg-violet-600 text-white" },
|
|
@@ -51316,6 +51897,15 @@ function HookResultsPanel({ results }) {
|
|
|
51316
51897
|
}) })
|
|
51317
51898
|
] });
|
|
51318
51899
|
}
|
|
51900
|
+
const { electron: electron$h } = window;
|
|
51901
|
+
function extractPath(url) {
|
|
51902
|
+
try {
|
|
51903
|
+
return new URL(url).pathname || "/";
|
|
51904
|
+
} catch {
|
|
51905
|
+
const match = url.match(/(?:https?:\/\/[^/]+)?(\/[^?]*)/);
|
|
51906
|
+
return match?.[1] ?? "/";
|
|
51907
|
+
}
|
|
51908
|
+
}
|
|
51319
51909
|
function SaveAsMockModal({ onClose }) {
|
|
51320
51910
|
const mocks = useStore((s) => s.mocks);
|
|
51321
51911
|
const addMock = useStore((s) => s.addMock);
|
|
@@ -51325,21 +51915,14 @@ function SaveAsMockModal({ onClose }) {
|
|
|
51325
51915
|
const response = activeTab?.lastResponse ?? null;
|
|
51326
51916
|
const activeRequestId = activeTab?.requestId ?? null;
|
|
51327
51917
|
const activeRequest = activeRequestId ? Object.values(collections).find((c) => c.data.requests[activeRequestId])?.data.requests[activeRequestId] : null;
|
|
51328
|
-
function extractPath(url) {
|
|
51329
|
-
try {
|
|
51330
|
-
return new URL(url).pathname || "/";
|
|
51331
|
-
} catch {
|
|
51332
|
-
const match = url.match(/(?:https?:\/\/[^/]+)?(\/[^?]*)/);
|
|
51333
|
-
return match?.[1] ?? "/";
|
|
51334
|
-
}
|
|
51335
|
-
}
|
|
51336
51918
|
const [targetMockId, setTargetMockId] = reactExports.useState(Object.keys(mocks)[0] ?? "__new__");
|
|
51337
51919
|
const [newServerName, setNewServerName] = reactExports.useState("Mock Server");
|
|
51338
51920
|
const [newServerPort, setNewServerPort] = reactExports.useState("3900");
|
|
51339
51921
|
const [method, setMethod] = reactExports.useState(activeRequest?.method ?? "GET");
|
|
51340
51922
|
const [path, setPath] = reactExports.useState(extractPath(activeRequest?.url ?? "/"));
|
|
51341
|
-
const [statusCode, setStatusCode] = reactExports.useState(response
|
|
51923
|
+
const [statusCode, setStatusCode] = reactExports.useState(response?.status ?? 200);
|
|
51342
51924
|
const [body, setBody] = reactExports.useState(() => {
|
|
51925
|
+
if (!response) return "";
|
|
51343
51926
|
try {
|
|
51344
51927
|
return JSON.stringify(JSON.parse(response.body), null, 2);
|
|
51345
51928
|
} catch {
|
|
@@ -51368,14 +51951,14 @@ function SaveAsMockModal({ onClose }) {
|
|
|
51368
51951
|
const entry = state.mocks[serverId];
|
|
51369
51952
|
const updated = { ...entry.data, name: newServerName, port: Number(newServerPort), routes: [route] };
|
|
51370
51953
|
updateMock(serverId, updated);
|
|
51371
|
-
await electron$
|
|
51954
|
+
await electron$h.saveMock(entry.relPath, updated);
|
|
51372
51955
|
const ws2 = useStore.getState().workspace;
|
|
51373
|
-
if (ws2) await electron$
|
|
51956
|
+
if (ws2) await electron$h.saveWorkspace(ws2);
|
|
51374
51957
|
} else {
|
|
51375
51958
|
const entry = useStore.getState().mocks[serverId];
|
|
51376
51959
|
const updated = { ...entry.data, routes: [...entry.data.routes, route] };
|
|
51377
51960
|
updateMock(serverId, updated);
|
|
51378
|
-
await electron$
|
|
51961
|
+
await electron$h.saveMock(entry.relPath, updated);
|
|
51379
51962
|
}
|
|
51380
51963
|
onClose();
|
|
51381
51964
|
} finally {
|
|
@@ -51499,6 +52082,39 @@ function SaveAsMockModal({ onClose }) {
|
|
|
51499
52082
|
}
|
|
51500
52083
|
) });
|
|
51501
52084
|
}
|
|
52085
|
+
function prettyJson(raw) {
|
|
52086
|
+
try {
|
|
52087
|
+
return JSON.stringify(JSON.parse(raw), null, 2);
|
|
52088
|
+
} catch {
|
|
52089
|
+
return raw;
|
|
52090
|
+
}
|
|
52091
|
+
}
|
|
52092
|
+
function prettyXml(raw) {
|
|
52093
|
+
try {
|
|
52094
|
+
const indent = " ";
|
|
52095
|
+
let result = "";
|
|
52096
|
+
let depth = 0;
|
|
52097
|
+
const tokens = raw.match(/<[^>]+>|[^<]+/g) ?? [];
|
|
52098
|
+
for (const token of tokens) {
|
|
52099
|
+
const text = token.trim();
|
|
52100
|
+
if (!text) continue;
|
|
52101
|
+
if (text.startsWith("<?") || text.startsWith("<!")) {
|
|
52102
|
+
result += indent.repeat(depth) + text + "\n";
|
|
52103
|
+
} else if (token.startsWith("</")) {
|
|
52104
|
+
depth = Math.max(0, depth - 1);
|
|
52105
|
+
result += indent.repeat(depth) + text + "\n";
|
|
52106
|
+
} else if (token.startsWith("<") && !token.endsWith("/>") && !token.includes("</")) {
|
|
52107
|
+
result += indent.repeat(depth) + text + "\n";
|
|
52108
|
+
depth++;
|
|
52109
|
+
} else {
|
|
52110
|
+
result += indent.repeat(depth) + text + "\n";
|
|
52111
|
+
}
|
|
52112
|
+
}
|
|
52113
|
+
return result.trimEnd();
|
|
52114
|
+
} catch {
|
|
52115
|
+
return raw;
|
|
52116
|
+
}
|
|
52117
|
+
}
|
|
51502
52118
|
function computeLineDiff(a, b) {
|
|
51503
52119
|
const aLines = a.split("\n");
|
|
51504
52120
|
const bLines = b.split("\n");
|
|
@@ -51527,20 +52143,20 @@ function computeLineDiff(a, b) {
|
|
|
51527
52143
|
}
|
|
51528
52144
|
return result;
|
|
51529
52145
|
}
|
|
52146
|
+
const lineStyle = {
|
|
52147
|
+
equal: "text-surface-400",
|
|
52148
|
+
removed: "bg-red-900/30 text-red-300",
|
|
52149
|
+
added: "bg-emerald-900/30 text-emerald-300"
|
|
52150
|
+
};
|
|
52151
|
+
const linePrefix = {
|
|
52152
|
+
equal: " ",
|
|
52153
|
+
removed: "-",
|
|
52154
|
+
added: "+"
|
|
52155
|
+
};
|
|
51530
52156
|
function DiffView({ pinned, current: current2 }) {
|
|
51531
52157
|
const pinnedBody = prettyJson(pinned.body);
|
|
51532
52158
|
const currentBody = prettyJson(current2.body);
|
|
51533
52159
|
const diffLines = computeLineDiff(pinnedBody, currentBody);
|
|
51534
|
-
const lineStyle = {
|
|
51535
|
-
equal: "text-surface-400",
|
|
51536
|
-
removed: "bg-red-900/30 text-red-300",
|
|
51537
|
-
added: "bg-emerald-900/30 text-emerald-300"
|
|
51538
|
-
};
|
|
51539
|
-
const linePrefix = {
|
|
51540
|
-
equal: " ",
|
|
51541
|
-
removed: "-",
|
|
51542
|
-
added: "+"
|
|
51543
|
-
};
|
|
51544
52160
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full overflow-auto", children: [
|
|
51545
52161
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-6 px-4 py-2 border-b border-surface-800 text-xs shrink-0", children: [
|
|
51546
52162
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -51585,6 +52201,94 @@ function DiffView({ pinned, current: current2 }) {
|
|
|
51585
52201
|
] })
|
|
51586
52202
|
] });
|
|
51587
52203
|
}
|
|
52204
|
+
function TestsPanel({ scriptResult }) {
|
|
52205
|
+
const sr = scriptResult;
|
|
52206
|
+
if (!sr || sr.testResults.length === 0 && !sr.preScriptError && !sr.postScriptError) {
|
|
52207
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center h-full text-surface-400 text-xs", children: [
|
|
52208
|
+
"No tests ran. Add ",
|
|
52209
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "mx-1 bg-surface-800 px-1 rounded", children: "pm.test()" }),
|
|
52210
|
+
" calls to your post-response script."
|
|
52211
|
+
] });
|
|
52212
|
+
}
|
|
52213
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 flex flex-col gap-2", children: [
|
|
52214
|
+
sr.preScriptError && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 p-2 rounded bg-red-900/30 border border-red-700", children: [
|
|
52215
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-400 text-xs font-bold shrink-0", children: "PRE-SCRIPT ERROR" }),
|
|
52216
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-300 text-xs font-mono", children: sr.preScriptError })
|
|
52217
|
+
] }),
|
|
52218
|
+
sr.postScriptError && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 p-2 rounded bg-red-900/30 border border-red-700", children: [
|
|
52219
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-400 text-xs font-bold shrink-0", children: "POST-SCRIPT ERROR" }),
|
|
52220
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-300 text-xs font-mono", children: sr.postScriptError })
|
|
52221
|
+
] }),
|
|
52222
|
+
sr.testResults.map((result, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
52223
|
+
"div",
|
|
52224
|
+
{
|
|
52225
|
+
className: `flex items-start gap-2 p-2 rounded border ${result.passed ? "bg-emerald-900/20 border-emerald-800" : "bg-red-900/20 border-red-800"}`,
|
|
52226
|
+
children: [
|
|
52227
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-xs font-bold shrink-0 ${result.passed ? "text-emerald-400" : "text-red-400"}`, children: result.passed ? "✓" : "✗" }),
|
|
52228
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
52229
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-white", children: result.name }),
|
|
52230
|
+
result.error && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] text-red-300 font-mono", children: result.error })
|
|
52231
|
+
] })
|
|
52232
|
+
]
|
|
52233
|
+
},
|
|
52234
|
+
i
|
|
52235
|
+
))
|
|
52236
|
+
] });
|
|
52237
|
+
}
|
|
52238
|
+
function RequestPanel({ sentRequest }) {
|
|
52239
|
+
if (!sentRequest) {
|
|
52240
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-full text-surface-400 text-xs", children: "Send a request to see what was transmitted." });
|
|
52241
|
+
}
|
|
52242
|
+
const hasBody = sentRequest.body !== void 0 && sentRequest.body !== "";
|
|
52243
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-h-0 overflow-y-auto text-xs font-mono", children: [
|
|
52244
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3 border-b border-surface-800 flex items-center gap-3", children: [
|
|
52245
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-bold text-blue-400 shrink-0", children: sentRequest.method }),
|
|
52246
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-white break-all", children: sentRequest.url })
|
|
52247
|
+
] }),
|
|
52248
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-2 border-b border-surface-800", children: [
|
|
52249
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-400 uppercase tracking-wider font-medium mb-1.5", children: "Headers" }),
|
|
52250
|
+
Object.keys(sentRequest.headers).length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600", children: "No headers sent" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("table", { className: "w-full", children: /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: Object.entries(sentRequest.headers).map(([k, v]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-surface-800/50 last:border-0", children: [
|
|
52251
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 pr-4 text-surface-400 w-56 align-top", children: k }),
|
|
52252
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 text-white break-all", children: v })
|
|
52253
|
+
] }, k)) }) })
|
|
52254
|
+
] }),
|
|
52255
|
+
hasBody && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-2", children: [
|
|
52256
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-400 uppercase tracking-wider font-medium mb-1.5", children: "Body" }),
|
|
52257
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-white whitespace-pre-wrap break-all text-[11px]", children: sentRequest.body })
|
|
52258
|
+
] })
|
|
52259
|
+
] });
|
|
52260
|
+
}
|
|
52261
|
+
function ConsolePanel({ scriptResult }) {
|
|
52262
|
+
const sr = scriptResult;
|
|
52263
|
+
const hasErrors = !!(sr?.preScriptError || sr?.postScriptError);
|
|
52264
|
+
const hasOutput = !!(sr && sr.consoleOutput.length > 0);
|
|
52265
|
+
if (!sr || !hasErrors && !hasOutput) {
|
|
52266
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center h-full text-surface-400 text-xs", children: [
|
|
52267
|
+
"No console output. Use ",
|
|
52268
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "mx-1 bg-surface-800 px-1 rounded", children: "console.log()" }),
|
|
52269
|
+
" in your scripts."
|
|
52270
|
+
] });
|
|
52271
|
+
}
|
|
52272
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 flex flex-col gap-2", children: [
|
|
52273
|
+
sr.preScriptError && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 p-2 rounded bg-red-900/30 border border-red-700", children: [
|
|
52274
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-400 text-xs font-bold shrink-0", children: "PRE-SCRIPT ERROR" }),
|
|
52275
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-300 text-xs font-mono", children: sr.preScriptError })
|
|
52276
|
+
] }),
|
|
52277
|
+
sr.postScriptError && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 p-2 rounded bg-red-900/30 border border-red-700", children: [
|
|
52278
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-400 text-xs font-bold shrink-0", children: "POST-SCRIPT ERROR" }),
|
|
52279
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-300 text-xs font-mono", children: sr.postScriptError })
|
|
52280
|
+
] }),
|
|
52281
|
+
hasOutput && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-0", children: sr.consoleOutput.map((line, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
52282
|
+
"div",
|
|
52283
|
+
{
|
|
52284
|
+
className: `text-xs font-mono py-0.5 border-b border-surface-800/50 last:border-0 ${line.startsWith("[error]") ? "text-red-300" : line.startsWith("[warn]") ? "text-amber-300" : line.startsWith("[set]") ? "text-cyan-400" : "text-surface-400"}`,
|
|
52285
|
+
children: line
|
|
52286
|
+
},
|
|
52287
|
+
i
|
|
52288
|
+
)) })
|
|
52289
|
+
] });
|
|
52290
|
+
}
|
|
52291
|
+
const { electron: electron$g } = window;
|
|
51588
52292
|
function ResponseViewer() {
|
|
51589
52293
|
const activeTab = useStore((s) => s.tabs.find((t2) => t2.id === s.activeTabId));
|
|
51590
52294
|
const activeTabId = useStore((s) => s.activeTabId);
|
|
@@ -51632,8 +52336,12 @@ function ResponseViewer() {
|
|
|
51632
52336
|
const req = Object.values(state.collections).find((c) => c.data.requests[requestId])?.data.requests[requestId];
|
|
51633
52337
|
if (!req) return;
|
|
51634
52338
|
const existing = req.postRequestScript ?? "";
|
|
52339
|
+
let cleaned = snippet2;
|
|
52340
|
+
if (existing.includes("const json = sp.response.json()")) {
|
|
52341
|
+
cleaned = cleaned.replace(/^\s*const json = sp\.response\.json\(\);?\s*\n?/m, "").replace(/\n\s*const json = sp\.response\.json\(\);?\s*\n/g, "\n");
|
|
52342
|
+
}
|
|
51635
52343
|
const sep = existing.trim() ? "\n\n" : "";
|
|
51636
|
-
updateRequest(requestId, { postRequestScript: existing + sep +
|
|
52344
|
+
updateRequest(requestId, { postRequestScript: existing + sep + cleaned });
|
|
51637
52345
|
if (activeTabId) {
|
|
51638
52346
|
setTabRequestTab(activeTabId, "scripts");
|
|
51639
52347
|
setTabScriptTab(activeTabId, "post");
|
|
@@ -51781,93 +52489,6 @@ function ResponseViewer() {
|
|
|
51781
52489
|
] }, k)) }) }) }) : tab === "tests" ? /* @__PURE__ */ jsxRuntimeExports.jsx(TestsPanel, { scriptResult }) : tab === "console" ? /* @__PURE__ */ jsxRuntimeExports.jsx(ConsolePanel, { scriptResult }) : tab === "request" ? /* @__PURE__ */ jsxRuntimeExports.jsx(RequestPanel, { sentRequest }) : null })
|
|
51782
52490
|
] });
|
|
51783
52491
|
}
|
|
51784
|
-
function TestsPanel({ scriptResult }) {
|
|
51785
|
-
const sr = scriptResult;
|
|
51786
|
-
if (!sr || sr.testResults.length === 0 && !sr.preScriptError && !sr.postScriptError) {
|
|
51787
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center h-full text-surface-400 text-xs", children: [
|
|
51788
|
-
"No tests ran. Add ",
|
|
51789
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "mx-1 bg-surface-800 px-1 rounded", children: "pm.test()" }),
|
|
51790
|
-
" calls to your post-response script."
|
|
51791
|
-
] });
|
|
51792
|
-
}
|
|
51793
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 flex flex-col gap-2", children: [
|
|
51794
|
-
sr.preScriptError && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 p-2 rounded bg-red-900/30 border border-red-700", children: [
|
|
51795
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-400 text-xs font-bold shrink-0", children: "PRE-SCRIPT ERROR" }),
|
|
51796
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-300 text-xs font-mono", children: sr.preScriptError })
|
|
51797
|
-
] }),
|
|
51798
|
-
sr.postScriptError && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 p-2 rounded bg-red-900/30 border border-red-700", children: [
|
|
51799
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-400 text-xs font-bold shrink-0", children: "POST-SCRIPT ERROR" }),
|
|
51800
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-300 text-xs font-mono", children: sr.postScriptError })
|
|
51801
|
-
] }),
|
|
51802
|
-
sr.testResults.map((result, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
51803
|
-
"div",
|
|
51804
|
-
{
|
|
51805
|
-
className: `flex items-start gap-2 p-2 rounded border ${result.passed ? "bg-emerald-900/20 border-emerald-800" : "bg-red-900/20 border-red-800"}`,
|
|
51806
|
-
children: [
|
|
51807
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-xs font-bold shrink-0 ${result.passed ? "text-emerald-400" : "text-red-400"}`, children: result.passed ? "✓" : "✗" }),
|
|
51808
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-0.5", children: [
|
|
51809
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-white", children: result.name }),
|
|
51810
|
-
result.error && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] text-red-300 font-mono", children: result.error })
|
|
51811
|
-
] })
|
|
51812
|
-
]
|
|
51813
|
-
},
|
|
51814
|
-
i
|
|
51815
|
-
))
|
|
51816
|
-
] });
|
|
51817
|
-
}
|
|
51818
|
-
function RequestPanel({ sentRequest }) {
|
|
51819
|
-
if (!sentRequest) {
|
|
51820
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-full text-surface-400 text-xs", children: "Send a request to see what was transmitted." });
|
|
51821
|
-
}
|
|
51822
|
-
const hasBody = sentRequest.body !== void 0 && sentRequest.body !== "";
|
|
51823
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-h-0 overflow-y-auto text-xs font-mono", children: [
|
|
51824
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3 border-b border-surface-800 flex items-center gap-3", children: [
|
|
51825
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-bold text-blue-400 shrink-0", children: sentRequest.method }),
|
|
51826
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-white break-all", children: sentRequest.url })
|
|
51827
|
-
] }),
|
|
51828
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-2 border-b border-surface-800", children: [
|
|
51829
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-400 uppercase tracking-wider font-medium mb-1.5", children: "Headers" }),
|
|
51830
|
-
Object.keys(sentRequest.headers).length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600", children: "No headers sent" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("table", { className: "w-full", children: /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: Object.entries(sentRequest.headers).map(([k, v]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { className: "border-b border-surface-800/50 last:border-0", children: [
|
|
51831
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 pr-4 text-surface-400 w-56 align-top", children: k }),
|
|
51832
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-1 text-white break-all", children: v })
|
|
51833
|
-
] }, k)) }) })
|
|
51834
|
-
] }),
|
|
51835
|
-
hasBody && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-2", children: [
|
|
51836
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-400 uppercase tracking-wider font-medium mb-1.5", children: "Body" }),
|
|
51837
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-white whitespace-pre-wrap break-all text-[11px]", children: sentRequest.body })
|
|
51838
|
-
] })
|
|
51839
|
-
] });
|
|
51840
|
-
}
|
|
51841
|
-
function ConsolePanel({ scriptResult }) {
|
|
51842
|
-
const sr = scriptResult;
|
|
51843
|
-
const hasErrors = !!(sr?.preScriptError || sr?.postScriptError);
|
|
51844
|
-
const hasOutput = !!(sr && sr.consoleOutput.length > 0);
|
|
51845
|
-
if (!sr || !hasErrors && !hasOutput) {
|
|
51846
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center h-full text-surface-400 text-xs", children: [
|
|
51847
|
-
"No console output. Use ",
|
|
51848
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { className: "mx-1 bg-surface-800 px-1 rounded", children: "console.log()" }),
|
|
51849
|
-
" in your scripts."
|
|
51850
|
-
] });
|
|
51851
|
-
}
|
|
51852
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 flex flex-col gap-2", children: [
|
|
51853
|
-
sr.preScriptError && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 p-2 rounded bg-red-900/30 border border-red-700", children: [
|
|
51854
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-400 text-xs font-bold shrink-0", children: "PRE-SCRIPT ERROR" }),
|
|
51855
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-300 text-xs font-mono", children: sr.preScriptError })
|
|
51856
|
-
] }),
|
|
51857
|
-
sr.postScriptError && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2 p-2 rounded bg-red-900/30 border border-red-700", children: [
|
|
51858
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-400 text-xs font-bold shrink-0", children: "POST-SCRIPT ERROR" }),
|
|
51859
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-300 text-xs font-mono", children: sr.postScriptError })
|
|
51860
|
-
] }),
|
|
51861
|
-
hasOutput && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-0", children: sr.consoleOutput.map((line, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
51862
|
-
"div",
|
|
51863
|
-
{
|
|
51864
|
-
className: `text-xs font-mono py-0.5 border-b border-surface-800/50 last:border-0 ${line.startsWith("[error]") ? "text-red-300" : line.startsWith("[warn]") ? "text-amber-300" : line.startsWith("[set]") ? "text-cyan-400" : "text-surface-400"}`,
|
|
51865
|
-
children: line
|
|
51866
|
-
},
|
|
51867
|
-
i
|
|
51868
|
-
)) })
|
|
51869
|
-
] });
|
|
51870
|
-
}
|
|
51871
52492
|
const { electron: electron$f } = window;
|
|
51872
52493
|
const TARGETS = [
|
|
51873
52494
|
{ id: "robot_framework", label: "Robot Framework", description: "Python RequestsLibrary keywords + test suite" },
|
|
@@ -53206,13 +53827,66 @@ const OPTIONS = [
|
|
|
53206
53827
|
{ id: "insomnia", label: "Insomnia", description: "Export v4 JSON" },
|
|
53207
53828
|
{ id: "bruno", label: "Bruno", description: "bruno.json collection file" }
|
|
53208
53829
|
];
|
|
53830
|
+
function listEndpoints(col) {
|
|
53831
|
+
const result = [];
|
|
53832
|
+
function walk(folder, path) {
|
|
53833
|
+
for (const id2 of folder.requestIds) {
|
|
53834
|
+
const req = col.requests[id2];
|
|
53835
|
+
if (req) result.push({ request: req, folderPath: path });
|
|
53836
|
+
}
|
|
53837
|
+
for (const sub of folder.folders) {
|
|
53838
|
+
walk(sub, [...path, sub.name]);
|
|
53839
|
+
}
|
|
53840
|
+
}
|
|
53841
|
+
walk(col.rootFolder, []);
|
|
53842
|
+
return result;
|
|
53843
|
+
}
|
|
53209
53844
|
function ImportModal({ onImport, onClose }) {
|
|
53845
|
+
const collections = useStore((s) => s.collections);
|
|
53846
|
+
const environments = useStore((s) => s.environments);
|
|
53847
|
+
const setActiveCollection = useStore((s) => s.setActiveCollection);
|
|
53848
|
+
const mergeIntoCollection = useStore((s) => s.mergeIntoCollection);
|
|
53849
|
+
const markCollectionClean = useStore((s) => s.markCollectionClean);
|
|
53210
53850
|
const [selected, setSelected] = reactExports.useState(null);
|
|
53211
53851
|
const [url, setUrl] = reactExports.useState("");
|
|
53212
53852
|
const [loading, setLoading] = reactExports.useState(false);
|
|
53213
53853
|
const [error2, setError] = reactExports.useState(null);
|
|
53214
53854
|
const urlInputRef = reactExports.useRef(null);
|
|
53215
|
-
|
|
53855
|
+
const [previewCol, setPreviewCol] = reactExports.useState(null);
|
|
53856
|
+
const [chosenIds, setChosenIds] = reactExports.useState(/* @__PURE__ */ new Set());
|
|
53857
|
+
const [target, setTarget] = reactExports.useState("__new__");
|
|
53858
|
+
const [newColName, setNewColName] = reactExports.useState("");
|
|
53859
|
+
const [baseUrl, setBaseUrl] = reactExports.useState("");
|
|
53860
|
+
const [varName, setVarName] = reactExports.useState("baseUrl");
|
|
53861
|
+
const [envTarget, setEnvTarget] = reactExports.useState("__new__");
|
|
53862
|
+
const [newEnvName, setNewEnvName] = reactExports.useState("");
|
|
53863
|
+
const endpoints = reactExports.useMemo(
|
|
53864
|
+
() => previewCol ? listEndpoints(previewCol) : [],
|
|
53865
|
+
[previewCol]
|
|
53866
|
+
);
|
|
53867
|
+
const grouped = reactExports.useMemo(() => {
|
|
53868
|
+
const map = /* @__PURE__ */ new Map();
|
|
53869
|
+
for (const ep of endpoints) {
|
|
53870
|
+
const key = ep.folderPath.join(" / ") || "(root)";
|
|
53871
|
+
const arr = map.get(key) ?? [];
|
|
53872
|
+
arr.push(ep);
|
|
53873
|
+
map.set(key, arr);
|
|
53874
|
+
}
|
|
53875
|
+
return Array.from(map.entries());
|
|
53876
|
+
}, [endpoints]);
|
|
53877
|
+
function enterPreview(col) {
|
|
53878
|
+
setPreviewCol(col);
|
|
53879
|
+
setNewColName(col.name);
|
|
53880
|
+
setChosenIds(new Set(Object.keys(col.requests)));
|
|
53881
|
+
const urls = Object.values(col.requests).map((r) => r.url).filter(Boolean);
|
|
53882
|
+
setBaseUrl(detectBaseUrl(urls));
|
|
53883
|
+
setVarName("baseUrl");
|
|
53884
|
+
const state = useStore.getState();
|
|
53885
|
+
const activeEnvId = state.activeEnvironmentId;
|
|
53886
|
+
setEnvTarget(activeEnvId && state.environments[activeEnvId] ? activeEnvId : "__new__");
|
|
53887
|
+
setNewEnvName(`${col.name} env`);
|
|
53888
|
+
}
|
|
53889
|
+
async function runFileImport(opt) {
|
|
53216
53890
|
setLoading(true);
|
|
53217
53891
|
setError(null);
|
|
53218
53892
|
try {
|
|
@@ -53221,8 +53895,16 @@ function ImportModal({ onImport, onClose }) {
|
|
|
53221
53895
|
if (opt.id === "openapi") col = await electron$8.importOpenApi();
|
|
53222
53896
|
if (opt.id === "insomnia") col = await electron$8.importInsomnia();
|
|
53223
53897
|
if (opt.id === "bruno") col = await electron$8.importBruno();
|
|
53224
|
-
|
|
53225
|
-
|
|
53898
|
+
if (!col) {
|
|
53899
|
+
setLoading(false);
|
|
53900
|
+
return;
|
|
53901
|
+
}
|
|
53902
|
+
if (opt.id === "openapi") {
|
|
53903
|
+
enterPreview(col);
|
|
53904
|
+
} else {
|
|
53905
|
+
onImport(col);
|
|
53906
|
+
onClose();
|
|
53907
|
+
}
|
|
53226
53908
|
} catch (err) {
|
|
53227
53909
|
setError(err instanceof Error ? err.message : String(err));
|
|
53228
53910
|
} finally {
|
|
@@ -53236,14 +53918,338 @@ function ImportModal({ onImport, onClose }) {
|
|
|
53236
53918
|
setError(null);
|
|
53237
53919
|
try {
|
|
53238
53920
|
const col = await electron$8.importOpenApiFromUrl(trimmed);
|
|
53239
|
-
|
|
53240
|
-
|
|
53921
|
+
if (col) enterPreview(col);
|
|
53922
|
+
} catch (err) {
|
|
53923
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
53924
|
+
} finally {
|
|
53925
|
+
setLoading(false);
|
|
53926
|
+
}
|
|
53927
|
+
}
|
|
53928
|
+
function toggleId(id2) {
|
|
53929
|
+
setChosenIds((prev) => {
|
|
53930
|
+
const next = new Set(prev);
|
|
53931
|
+
if (next.has(id2)) next.delete(id2);
|
|
53932
|
+
else next.add(id2);
|
|
53933
|
+
return next;
|
|
53934
|
+
});
|
|
53935
|
+
}
|
|
53936
|
+
function toggleGroup(ids) {
|
|
53937
|
+
setChosenIds((prev) => {
|
|
53938
|
+
const next = new Set(prev);
|
|
53939
|
+
const allSelected = ids.every((id2) => next.has(id2));
|
|
53940
|
+
if (allSelected) ids.forEach((id2) => next.delete(id2));
|
|
53941
|
+
else ids.forEach((id2) => next.add(id2));
|
|
53942
|
+
return next;
|
|
53943
|
+
});
|
|
53944
|
+
}
|
|
53945
|
+
function selectAll2() {
|
|
53946
|
+
setChosenIds(new Set(endpoints.map((e) => e.request.id)));
|
|
53947
|
+
}
|
|
53948
|
+
function selectNone() {
|
|
53949
|
+
setChosenIds(/* @__PURE__ */ new Set());
|
|
53950
|
+
}
|
|
53951
|
+
async function confirmImport() {
|
|
53952
|
+
if (!previewCol) return;
|
|
53953
|
+
const picked = endpoints.filter((e) => chosenIds.has(e.request.id));
|
|
53954
|
+
if (!picked.length) {
|
|
53955
|
+
setError("Pick at least one endpoint");
|
|
53956
|
+
return;
|
|
53957
|
+
}
|
|
53958
|
+
const trimmedVarName = varName.trim();
|
|
53959
|
+
const trimmedBaseUrl = baseUrl.trim();
|
|
53960
|
+
const useVariable = Boolean(trimmedVarName && trimmedBaseUrl);
|
|
53961
|
+
if (trimmedBaseUrl && !trimmedVarName) {
|
|
53962
|
+
setError("Variable name is required when extracting base URL");
|
|
53963
|
+
return;
|
|
53964
|
+
}
|
|
53965
|
+
setLoading(true);
|
|
53966
|
+
setError(null);
|
|
53967
|
+
try {
|
|
53968
|
+
const rewriteUrl = (u) => {
|
|
53969
|
+
if (!useVariable) return u;
|
|
53970
|
+
return u.startsWith(trimmedBaseUrl) ? `{{${trimmedVarName}}}${u.slice(trimmedBaseUrl.length)}` : u;
|
|
53971
|
+
};
|
|
53972
|
+
for (const ep of picked) {
|
|
53973
|
+
ep.request.url = rewriteUrl(ep.request.url);
|
|
53974
|
+
}
|
|
53975
|
+
if (useVariable) {
|
|
53976
|
+
await persistBaseUrlVariable(trimmedVarName, trimmedBaseUrl);
|
|
53977
|
+
}
|
|
53978
|
+
if (target === "__new__") {
|
|
53979
|
+
const filtered = {
|
|
53980
|
+
...previewCol,
|
|
53981
|
+
name: newColName.trim() || previewCol.name,
|
|
53982
|
+
requests: {},
|
|
53983
|
+
rootFolder: pruneFolder(previewCol.rootFolder, previewCol, chosenIds, {})
|
|
53984
|
+
};
|
|
53985
|
+
filtered.requests = collectRequestsByFolder(filtered.rootFolder, previewCol);
|
|
53986
|
+
onImport(filtered);
|
|
53987
|
+
onClose();
|
|
53988
|
+
} else {
|
|
53989
|
+
const targetCol = collections[target]?.data;
|
|
53990
|
+
if (!targetCol) throw new Error("Target collection not found");
|
|
53991
|
+
const prunedRoot = pruneFolder(previewCol.rootFolder, previewCol, chosenIds, {});
|
|
53992
|
+
const prunedRequests = collectRequestsByFolder(prunedRoot, previewCol);
|
|
53993
|
+
mergeIntoCollection(target, prunedRoot, prunedRequests);
|
|
53994
|
+
const entry = useStore.getState().collections[target];
|
|
53995
|
+
if (entry) {
|
|
53996
|
+
await electron$8.saveCollection(entry.relPath, entry.data);
|
|
53997
|
+
markCollectionClean(target);
|
|
53998
|
+
}
|
|
53999
|
+
setActiveCollection(target);
|
|
54000
|
+
onImport(null);
|
|
54001
|
+
onClose();
|
|
54002
|
+
}
|
|
53241
54003
|
} catch (err) {
|
|
53242
54004
|
setError(err instanceof Error ? err.message : String(err));
|
|
53243
54005
|
} finally {
|
|
53244
54006
|
setLoading(false);
|
|
53245
54007
|
}
|
|
53246
54008
|
}
|
|
54009
|
+
async function persistBaseUrlVariable(name2, value) {
|
|
54010
|
+
const state = useStore.getState();
|
|
54011
|
+
if (envTarget === "__new__") {
|
|
54012
|
+
const desiredName = newEnvName.trim() || "New Environment";
|
|
54013
|
+
const existingNames = Object.values(state.environments).map((e) => e.data.name);
|
|
54014
|
+
const finalName = uniqueEnvName(desiredName, existingNames);
|
|
54015
|
+
const envId = v4();
|
|
54016
|
+
const env = {
|
|
54017
|
+
version: "1.0",
|
|
54018
|
+
id: envId,
|
|
54019
|
+
name: finalName,
|
|
54020
|
+
variables: [{ key: name2, value, enabled: true }]
|
|
54021
|
+
};
|
|
54022
|
+
const relPath = envRelPath(finalName, envId);
|
|
54023
|
+
await electron$8.saveEnvironment(relPath, env);
|
|
54024
|
+
useStore.setState((s) => {
|
|
54025
|
+
s.environments[envId] = { relPath, data: env };
|
|
54026
|
+
if (!s.activeEnvironmentId) s.activeEnvironmentId = envId;
|
|
54027
|
+
if (s.workspace && !s.workspace.environments.includes(relPath)) {
|
|
54028
|
+
s.workspace.environments = [...s.workspace.environments, relPath];
|
|
54029
|
+
}
|
|
54030
|
+
return s;
|
|
54031
|
+
});
|
|
54032
|
+
const ws2 = useStore.getState().workspace;
|
|
54033
|
+
if (ws2) await electron$8.saveWorkspace(ws2);
|
|
54034
|
+
} else {
|
|
54035
|
+
const entry = state.environments[envTarget];
|
|
54036
|
+
if (!entry) throw new Error("Target environment not found");
|
|
54037
|
+
const updated = { ...entry.data };
|
|
54038
|
+
const idx = updated.variables.findIndex((v) => v.key === name2);
|
|
54039
|
+
if (idx >= 0) {
|
|
54040
|
+
if (!updated.variables[idx].value) {
|
|
54041
|
+
updated.variables = updated.variables.map(
|
|
54042
|
+
(v, i) => i === idx ? { ...v, value, enabled: true } : v
|
|
54043
|
+
);
|
|
54044
|
+
}
|
|
54045
|
+
} else {
|
|
54046
|
+
updated.variables = [...updated.variables, { key: name2, value, enabled: true }];
|
|
54047
|
+
}
|
|
54048
|
+
await electron$8.saveEnvironment(entry.relPath, updated);
|
|
54049
|
+
useStore.getState().updateEnvironment(envTarget, updated);
|
|
54050
|
+
}
|
|
54051
|
+
}
|
|
54052
|
+
if (previewCol) {
|
|
54053
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60", onClick: onClose, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54054
|
+
"div",
|
|
54055
|
+
{
|
|
54056
|
+
className: "bg-surface-900 border border-surface-700 rounded-xl shadow-2xl w-[640px] max-h-[80vh] p-5 flex flex-col gap-4",
|
|
54057
|
+
onClick: (e) => e.stopPropagation(),
|
|
54058
|
+
children: [
|
|
54059
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
54060
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-sm font-semibold text-surface-100", children: [
|
|
54061
|
+
"Import OpenAPI — ",
|
|
54062
|
+
previewCol.name
|
|
54063
|
+
] }),
|
|
54064
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54065
|
+
"button",
|
|
54066
|
+
{
|
|
54067
|
+
onClick: onClose,
|
|
54068
|
+
className: "text-surface-500 hover:text-surface-300 text-lg leading-none",
|
|
54069
|
+
children: "×"
|
|
54070
|
+
}
|
|
54071
|
+
)
|
|
54072
|
+
] }),
|
|
54073
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 border border-surface-800 rounded-lg p-3", children: [
|
|
54074
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-500 uppercase tracking-wider font-medium", children: "Destination" }),
|
|
54075
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54076
|
+
"select",
|
|
54077
|
+
{
|
|
54078
|
+
value: target,
|
|
54079
|
+
onChange: (e) => setTarget(e.target.value),
|
|
54080
|
+
className: "text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1.5 focus:outline-none focus:border-blue-500",
|
|
54081
|
+
children: [
|
|
54082
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "__new__", children: "Create new collection…" }),
|
|
54083
|
+
Object.values(collections).map((c) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: c.data.id, children: c.data.name }, c.data.id))
|
|
54084
|
+
]
|
|
54085
|
+
}
|
|
54086
|
+
),
|
|
54087
|
+
target === "__new__" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54088
|
+
"input",
|
|
54089
|
+
{
|
|
54090
|
+
value: newColName,
|
|
54091
|
+
onChange: (e) => setNewColName(e.target.value),
|
|
54092
|
+
placeholder: "Collection name",
|
|
54093
|
+
className: "text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1.5 focus:outline-none focus:border-blue-500"
|
|
54094
|
+
}
|
|
54095
|
+
)
|
|
54096
|
+
] }),
|
|
54097
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 border border-surface-800 rounded-lg p-3", children: [
|
|
54098
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-500 uppercase tracking-wider font-medium", children: "Base URL → variable" }),
|
|
54099
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
54100
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54101
|
+
"input",
|
|
54102
|
+
{
|
|
54103
|
+
value: baseUrl,
|
|
54104
|
+
onChange: (e) => setBaseUrl(e.target.value),
|
|
54105
|
+
placeholder: "https://api.example.com/v1",
|
|
54106
|
+
className: "flex-1 text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1.5 focus:outline-none focus:border-blue-500 placeholder-surface-600 font-mono"
|
|
54107
|
+
}
|
|
54108
|
+
),
|
|
54109
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-surface-500 self-center", children: "→" }),
|
|
54110
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54111
|
+
"input",
|
|
54112
|
+
{
|
|
54113
|
+
value: varName,
|
|
54114
|
+
onChange: (e) => setVarName(e.target.value),
|
|
54115
|
+
placeholder: "baseUrl",
|
|
54116
|
+
className: "w-32 text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1.5 focus:outline-none focus:border-blue-500 placeholder-surface-600 font-mono"
|
|
54117
|
+
}
|
|
54118
|
+
)
|
|
54119
|
+
] }),
|
|
54120
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-500", children: "Leave the URL field empty to keep absolute URLs in each request." }),
|
|
54121
|
+
baseUrl.trim() && varName.trim() && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
54122
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54123
|
+
"select",
|
|
54124
|
+
{
|
|
54125
|
+
value: envTarget,
|
|
54126
|
+
onChange: (e) => setEnvTarget(e.target.value),
|
|
54127
|
+
className: "text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1.5 focus:outline-none focus:border-blue-500",
|
|
54128
|
+
children: [
|
|
54129
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "__new__", children: "Create new environment…" }),
|
|
54130
|
+
Object.values(environments).map((e) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: e.data.id, children: e.data.name }, e.data.id))
|
|
54131
|
+
]
|
|
54132
|
+
}
|
|
54133
|
+
),
|
|
54134
|
+
envTarget === "__new__" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54135
|
+
"input",
|
|
54136
|
+
{
|
|
54137
|
+
value: newEnvName,
|
|
54138
|
+
onChange: (e) => setNewEnvName(e.target.value),
|
|
54139
|
+
placeholder: "Environment name",
|
|
54140
|
+
className: "text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1.5 focus:outline-none focus:border-blue-500"
|
|
54141
|
+
}
|
|
54142
|
+
)
|
|
54143
|
+
] })
|
|
54144
|
+
] }),
|
|
54145
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
54146
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[10px] text-surface-500 uppercase tracking-wider font-medium", children: [
|
|
54147
|
+
"Endpoints (",
|
|
54148
|
+
chosenIds.size,
|
|
54149
|
+
" / ",
|
|
54150
|
+
endpoints.length,
|
|
54151
|
+
")"
|
|
54152
|
+
] }),
|
|
54153
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
54154
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: selectAll2, className: "text-[10px] text-blue-400 hover:text-blue-300", children: "Select all" }),
|
|
54155
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: selectNone, className: "text-[10px] text-blue-400 hover:text-blue-300", children: "Select none" })
|
|
54156
|
+
] })
|
|
54157
|
+
] }),
|
|
54158
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-h-0 overflow-y-auto border border-surface-800 rounded-lg", children: [
|
|
54159
|
+
grouped.map(([groupName, items2]) => {
|
|
54160
|
+
const ids = items2.map((i) => i.request.id);
|
|
54161
|
+
const allOn = ids.every((id2) => chosenIds.has(id2));
|
|
54162
|
+
const someOn = !allOn && ids.some((id2) => chosenIds.has(id2));
|
|
54163
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-b border-surface-800 last:border-b-0", children: [
|
|
54164
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54165
|
+
"button",
|
|
54166
|
+
{
|
|
54167
|
+
onClick: () => toggleGroup(ids),
|
|
54168
|
+
className: "w-full flex items-center gap-2 px-3 py-2 bg-surface-850 hover:bg-surface-800 text-left",
|
|
54169
|
+
children: [
|
|
54170
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54171
|
+
"input",
|
|
54172
|
+
{
|
|
54173
|
+
type: "checkbox",
|
|
54174
|
+
checked: allOn,
|
|
54175
|
+
ref: (el) => {
|
|
54176
|
+
if (el) el.indeterminate = someOn;
|
|
54177
|
+
},
|
|
54178
|
+
onChange: () => toggleGroup(ids),
|
|
54179
|
+
onClick: (e) => e.stopPropagation(),
|
|
54180
|
+
className: "accent-blue-500"
|
|
54181
|
+
}
|
|
54182
|
+
),
|
|
54183
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-semibold text-surface-200", children: groupName }),
|
|
54184
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-surface-500", children: [
|
|
54185
|
+
"(",
|
|
54186
|
+
items2.length,
|
|
54187
|
+
")"
|
|
54188
|
+
] })
|
|
54189
|
+
]
|
|
54190
|
+
}
|
|
54191
|
+
),
|
|
54192
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: items2.map((ep) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54193
|
+
"label",
|
|
54194
|
+
{
|
|
54195
|
+
className: "flex items-center gap-2 px-3 py-1.5 pl-8 hover:bg-surface-850 cursor-pointer",
|
|
54196
|
+
children: [
|
|
54197
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54198
|
+
"input",
|
|
54199
|
+
{
|
|
54200
|
+
type: "checkbox",
|
|
54201
|
+
checked: chosenIds.has(ep.request.id),
|
|
54202
|
+
onChange: () => toggleId(ep.request.id),
|
|
54203
|
+
className: "accent-blue-500"
|
|
54204
|
+
}
|
|
54205
|
+
),
|
|
54206
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-mono font-bold ${methodColor$1(ep.request.method)}`, children: ep.request.method }),
|
|
54207
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-surface-200 truncate", children: ep.request.name })
|
|
54208
|
+
]
|
|
54209
|
+
},
|
|
54210
|
+
ep.request.id
|
|
54211
|
+
)) })
|
|
54212
|
+
] }, groupName);
|
|
54213
|
+
}),
|
|
54214
|
+
!grouped.length && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-surface-500 p-3", children: "No endpoints found in spec." })
|
|
54215
|
+
] }),
|
|
54216
|
+
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-red-400", children: error2 }),
|
|
54217
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between pt-1", children: [
|
|
54218
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54219
|
+
"button",
|
|
54220
|
+
{
|
|
54221
|
+
onClick: () => {
|
|
54222
|
+
setPreviewCol(null);
|
|
54223
|
+
setError(null);
|
|
54224
|
+
},
|
|
54225
|
+
className: "px-3 py-1.5 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
54226
|
+
children: "Back"
|
|
54227
|
+
}
|
|
54228
|
+
),
|
|
54229
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
54230
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54231
|
+
"button",
|
|
54232
|
+
{
|
|
54233
|
+
onClick: onClose,
|
|
54234
|
+
className: "px-3 py-1.5 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
54235
|
+
children: "Cancel"
|
|
54236
|
+
}
|
|
54237
|
+
),
|
|
54238
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54239
|
+
"button",
|
|
54240
|
+
{
|
|
54241
|
+
disabled: loading || chosenIds.size === 0 || target === "__new__" && !newColName.trim(),
|
|
54242
|
+
onClick: confirmImport,
|
|
54243
|
+
className: "px-3 py-1.5 text-xs bg-blue-700 hover:bg-blue-600 disabled:bg-surface-800 disabled:text-surface-600 rounded transition-colors",
|
|
54244
|
+
children: loading ? "Importing…" : "Import"
|
|
54245
|
+
}
|
|
54246
|
+
)
|
|
54247
|
+
] })
|
|
54248
|
+
] })
|
|
54249
|
+
]
|
|
54250
|
+
}
|
|
54251
|
+
) });
|
|
54252
|
+
}
|
|
53247
54253
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60", onClick: onClose, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
53248
54254
|
"div",
|
|
53249
54255
|
{
|
|
@@ -53319,7 +54325,7 @@ function ImportModal({ onImport, onClose }) {
|
|
|
53319
54325
|
disabled: !selected || loading,
|
|
53320
54326
|
onClick: () => {
|
|
53321
54327
|
const opt = OPTIONS.find((o) => o.id === selected);
|
|
53322
|
-
if (opt)
|
|
54328
|
+
if (opt) runFileImport(opt);
|
|
53323
54329
|
},
|
|
53324
54330
|
className: "px-3 py-1.5 text-xs bg-blue-700 hover:bg-blue-600 disabled:bg-surface-800 disabled:text-surface-600 rounded transition-colors",
|
|
53325
54331
|
children: loading ? "Importing…" : "Choose File"
|
|
@@ -53330,6 +54336,63 @@ function ImportModal({ onImport, onClose }) {
|
|
|
53330
54336
|
}
|
|
53331
54337
|
) });
|
|
53332
54338
|
}
|
|
54339
|
+
function detectBaseUrl(urls) {
|
|
54340
|
+
if (!urls.length) return "";
|
|
54341
|
+
let prefix2 = urls[0];
|
|
54342
|
+
for (const u of urls.slice(1)) {
|
|
54343
|
+
let i = 0;
|
|
54344
|
+
while (i < prefix2.length && i < u.length && prefix2[i] === u[i]) i++;
|
|
54345
|
+
prefix2 = prefix2.slice(0, i);
|
|
54346
|
+
if (!prefix2) break;
|
|
54347
|
+
}
|
|
54348
|
+
if (!prefix2.includes("://")) return "";
|
|
54349
|
+
const protoEnd = prefix2.indexOf("://") + 3;
|
|
54350
|
+
const lastSlash = prefix2.lastIndexOf("/");
|
|
54351
|
+
if (lastSlash > protoEnd) prefix2 = prefix2.slice(0, lastSlash);
|
|
54352
|
+
return prefix2.replace(/\/$/, "");
|
|
54353
|
+
}
|
|
54354
|
+
function uniqueEnvName(base2, existing) {
|
|
54355
|
+
if (!existing.includes(base2)) return base2;
|
|
54356
|
+
let i = 2;
|
|
54357
|
+
while (existing.includes(`${base2} (${i})`)) i++;
|
|
54358
|
+
return `${base2} (${i})`;
|
|
54359
|
+
}
|
|
54360
|
+
function methodColor$1(method) {
|
|
54361
|
+
switch (method) {
|
|
54362
|
+
case "GET":
|
|
54363
|
+
return "text-emerald-400";
|
|
54364
|
+
case "POST":
|
|
54365
|
+
return "text-amber-400";
|
|
54366
|
+
case "PUT":
|
|
54367
|
+
return "text-sky-400";
|
|
54368
|
+
case "PATCH":
|
|
54369
|
+
return "text-violet-400";
|
|
54370
|
+
case "DELETE":
|
|
54371
|
+
return "text-red-400";
|
|
54372
|
+
default:
|
|
54373
|
+
return "text-surface-300";
|
|
54374
|
+
}
|
|
54375
|
+
}
|
|
54376
|
+
function pruneFolder(src, _col, keep, _out) {
|
|
54377
|
+
const subFolders = src.folders.map((f) => pruneFolder(f, _col, keep)).filter((f) => f.requestIds.length > 0 || f.folders.length > 0);
|
|
54378
|
+
const requestIds = src.requestIds.filter((id2) => keep.has(id2));
|
|
54379
|
+
return {
|
|
54380
|
+
...src,
|
|
54381
|
+
folders: subFolders,
|
|
54382
|
+
requestIds
|
|
54383
|
+
};
|
|
54384
|
+
}
|
|
54385
|
+
function collectRequestsByFolder(folder, src) {
|
|
54386
|
+
const out = {};
|
|
54387
|
+
function walk(f) {
|
|
54388
|
+
for (const id2 of f.requestIds) {
|
|
54389
|
+
if (src.requests[id2]) out[id2] = src.requests[id2];
|
|
54390
|
+
}
|
|
54391
|
+
for (const sub of f.folders) walk(sub);
|
|
54392
|
+
}
|
|
54393
|
+
walk(folder);
|
|
54394
|
+
return out;
|
|
54395
|
+
}
|
|
53333
54396
|
const { electron: electron$7 } = window;
|
|
53334
54397
|
const ZOOM_STEPS = [0.75, 0.9, 1, 1.1, 1.25, 1.5];
|
|
53335
54398
|
function PreferencesPopover() {
|
|
@@ -53666,8 +54729,13 @@ function buildHtmlReport(results, summary, meta2 = {}) {
|
|
|
53666
54729
|
after: "AFTER",
|
|
53667
54730
|
afterAll: "AFTER ALL"
|
|
53668
54731
|
};
|
|
54732
|
+
let lastScopeKey = null;
|
|
53669
54733
|
const cards = results.map((r, idx) => {
|
|
53670
|
-
const
|
|
54734
|
+
const scopeKey = (r.scopePath ?? []).join(" / ");
|
|
54735
|
+
const groupHeading = scopeKey && scopeKey !== lastScopeKey ? ` <div class="scope-heading">${esc2(scopeKey)}</div>
|
|
54736
|
+
` : "";
|
|
54737
|
+
lastScopeKey = scopeKey;
|
|
54738
|
+
const statusCls = r.status === "passed" ? "badge-pass" : r.status === "failed" ? "badge-fail" : r.status === "skipped" ? "badge-skip" : "badge-err";
|
|
53671
54739
|
const httpCls = r.httpStatus && r.httpStatus < 300 ? "http-ok" : r.httpStatus && r.httpStatus < 400 ? "http-redir" : "http-err";
|
|
53672
54740
|
const dur = r.durationMs != null ? `${r.durationMs} ms` : "—";
|
|
53673
54741
|
const label = r.iterationLabel ? ` <span class="muted">#${esc2(r.iterationLabel)}</span>` : "";
|
|
@@ -53705,7 +54773,7 @@ function buildHtmlReport(results, summary, meta2 = {}) {
|
|
|
53705
54773
|
${resp.body ? `<div class="section-label">Body</div><pre class="code-block">${prettyJson2(resp.body)}</pre>` : ""}
|
|
53706
54774
|
</div>` : "";
|
|
53707
54775
|
const hookCls = hookLabel ? r.hookType?.startsWith("before") ? "card-hook-before" : "card-hook-after" : "";
|
|
53708
|
-
return
|
|
54776
|
+
return `${groupHeading}
|
|
53709
54777
|
<div class="card ${hookCls}" id="r${idx}">
|
|
53710
54778
|
<div class="card-header" onclick="toggle(${idx})">
|
|
53711
54779
|
<span class="chevron" id="ch${idx}">▶</span>
|
|
@@ -53746,8 +54814,11 @@ function buildHtmlReport(results, summary, meta2 = {}) {
|
|
|
53746
54814
|
.stat-pass .stat-val { color: #3fb950; }
|
|
53747
54815
|
.stat-fail .stat-val { color: #f85149; }
|
|
53748
54816
|
.stat-err .stat-val { color: #d29922; }
|
|
54817
|
+
.stat-skip .stat-val { color: #8b949e; }
|
|
53749
54818
|
/* Cards */
|
|
53750
54819
|
.card { border: 1px solid #21262d; border-radius: 8px; margin-bottom: 8px; overflow: hidden; }
|
|
54820
|
+
.scope-heading { margin: 18px 0 6px; padding: 4px 2px; font-size: 11px; font-weight: 600; color: #8b949e; text-transform: uppercase; letter-spacing: 0.5px; border-bottom: 1px solid #21262d; }
|
|
54821
|
+
.scope-heading::before { content: "▸ "; color: #484f58; }
|
|
53751
54822
|
.card-header { display: flex; align-items: baseline; gap: 8px; padding: 10px 14px; cursor: pointer; user-select: none; }
|
|
53752
54823
|
.card-header:hover { background: #161b22; }
|
|
53753
54824
|
.chevron { font-size: 10px; color: #8b949e; min-width: 10px; transition: transform .15s; }
|
|
@@ -53759,6 +54830,7 @@ function buildHtmlReport(results, summary, meta2 = {}) {
|
|
|
53759
54830
|
.badge-pass { background: #0d3a1e; color: #3fb950; }
|
|
53760
54831
|
.badge-fail { background: #3d1014; color: #f85149; }
|
|
53761
54832
|
.badge-err { background: #3d2a00; color: #d29922; }
|
|
54833
|
+
.badge-skip { background: #21262d; color: #8b949e; }
|
|
53762
54834
|
.method { font-family: monospace; font-size: 11px; font-weight: 700; color: #79c0ff; white-space: nowrap; }
|
|
53763
54835
|
.method-badge { display: inline-block; font-family: monospace; font-size: 11px; font-weight: 700; color: #79c0ff; min-width: 52px; }
|
|
53764
54836
|
.http-badge { font-family: monospace; font-size: 11px; font-weight: 600; white-space: nowrap; }
|
|
@@ -53812,6 +54884,7 @@ function buildHtmlReport(results, summary, meta2 = {}) {
|
|
|
53812
54884
|
<div class="stat stat-pass"><div class="stat-val">${summary.passed}</div><div class="stat-lbl">Passed</div></div>
|
|
53813
54885
|
<div class="stat stat-fail"><div class="stat-val">${summary.failed}</div><div class="stat-lbl">Failed</div></div>
|
|
53814
54886
|
<div class="stat stat-err"><div class="stat-val">${summary.errors}</div><div class="stat-lbl">Errors</div></div>
|
|
54887
|
+
<div class="stat stat-skip"><div class="stat-val">${summary.skipped ?? 0}</div><div class="stat-lbl">No tests</div></div>
|
|
53815
54888
|
<div class="stat"><div class="stat-val">${passRate}%</div><div class="stat-lbl">Pass rate</div></div>
|
|
53816
54889
|
<div class="stat"><div class="stat-val">${summary.durationMs} ms</div><div class="stat-lbl">Duration</div></div>
|
|
53817
54890
|
</div>
|
|
@@ -53855,6 +54928,8 @@ function buildJUnitReport(results, summary, meta2 = {}) {
|
|
|
53855
54928
|
failures.push(` <error message="${esc2(r.preScriptError)}" type="PreScriptError" />`);
|
|
53856
54929
|
} else if (r.postScriptError) {
|
|
53857
54930
|
failures.push(` <error message="${esc2(r.postScriptError)}" type="PostScriptError" />`);
|
|
54931
|
+
} else if (r.status === "skipped") {
|
|
54932
|
+
failures.push(' <skipped message="No assertions defined for this request" />');
|
|
53858
54933
|
} else if (r.testResults?.length) {
|
|
53859
54934
|
for (const t2 of r.testResults) {
|
|
53860
54935
|
if (!t2.passed) {
|
|
@@ -53869,10 +54944,11 @@ ${failures.join("\n")}
|
|
|
53869
54944
|
` : "";
|
|
53870
54945
|
return ` <testcase name="${name2}" classname="${classname}" time="${timeSec}">${inner}</testcase>`;
|
|
53871
54946
|
});
|
|
54947
|
+
const skipped = summary.skipped ?? 0;
|
|
53872
54948
|
const lines = [
|
|
53873
54949
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
53874
|
-
`<testsuites name="${suiteName}" tests="${summary.total}" failures="${summary.failed}" errors="${summary.errors}" time="${totalSec}">`,
|
|
53875
|
-
` <testsuite name="${suiteName}" tests="${summary.total}" failures="${summary.failed}" errors="${summary.errors}" time="${totalSec}" timestamp="${ts}">`,
|
|
54950
|
+
`<testsuites name="${suiteName}" tests="${summary.total}" failures="${summary.failed}" errors="${summary.errors}" skipped="${skipped}" time="${totalSec}">`,
|
|
54951
|
+
` <testsuite name="${suiteName}" tests="${summary.total}" failures="${summary.failed}" errors="${summary.errors}" skipped="${skipped}" time="${totalSec}" timestamp="${ts}">`,
|
|
53876
54952
|
...cases,
|
|
53877
54953
|
" </testsuite>",
|
|
53878
54954
|
"</testsuites>"
|
|
@@ -53972,7 +55048,7 @@ function allTagsIn(collectionId, folderId) {
|
|
|
53972
55048
|
const state = useStore.getState();
|
|
53973
55049
|
const col = state.collections[collectionId]?.data;
|
|
53974
55050
|
if (!col) return [];
|
|
53975
|
-
const rootFolder = folderId ? findFolder(col.rootFolder, folderId) ?? col.rootFolder : col.rootFolder;
|
|
55051
|
+
const rootFolder = folderId ? findFolder$1(col.rootFolder, folderId) ?? col.rootFolder : col.rootFolder;
|
|
53976
55052
|
return collectAllTags(rootFolder, col.requests);
|
|
53977
55053
|
}
|
|
53978
55054
|
function StatusDot({ status }) {
|
|
@@ -53981,7 +55057,8 @@ function StatusDot({ status }) {
|
|
|
53981
55057
|
running: "bg-blue-400 animate-pulse",
|
|
53982
55058
|
passed: "bg-emerald-500",
|
|
53983
55059
|
failed: "bg-red-500",
|
|
53984
|
-
error: "bg-orange-500"
|
|
55060
|
+
error: "bg-orange-500",
|
|
55061
|
+
skipped: "bg-surface-500"
|
|
53985
55062
|
};
|
|
53986
55063
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `inline-block w-2 h-2 rounded-full shrink-0 ${colors[status] ?? "bg-surface-700"}` });
|
|
53987
55064
|
}
|
|
@@ -54007,7 +55084,7 @@ function RunnerModal() {
|
|
|
54007
55084
|
const { collectionId, folderId } = runnerModal;
|
|
54008
55085
|
const colEntry = collectionId ? collections[collectionId] : null;
|
|
54009
55086
|
const colName = colEntry?.data.name ?? "Collection";
|
|
54010
|
-
const folderName = folderId && colEntry ? findFolder(colEntry.data.rootFolder, folderId)?.name ?? "Folder" : null;
|
|
55087
|
+
const folderName = folderId && colEntry ? findFolder$1(colEntry.data.rootFolder, folderId)?.name ?? "Folder" : null;
|
|
54011
55088
|
const dataSet = colEntry?.data.dataSet ?? { columns: [], rows: [] };
|
|
54012
55089
|
const iterCount = dataSet.rows.length;
|
|
54013
55090
|
const availableTags = collectionId ? allTagsIn(collectionId, folderId) : [];
|
|
@@ -54053,7 +55130,8 @@ function RunnerModal() {
|
|
|
54053
55130
|
iterationLabel: item.iterationLabel,
|
|
54054
55131
|
isHook: item.isHook,
|
|
54055
55132
|
hookType: item.hookType,
|
|
54056
|
-
scopeId: item.scopeId
|
|
55133
|
+
scopeId: item.scopeId,
|
|
55134
|
+
scopePath: item.scopePath
|
|
54057
55135
|
})));
|
|
54058
55136
|
setSummary(null);
|
|
54059
55137
|
setRunnerRunning(true);
|
|
@@ -54212,45 +55290,55 @@ function RunnerModal() {
|
|
|
54212
55290
|
] })
|
|
54213
55291
|
] })
|
|
54214
55292
|
] }),
|
|
54215
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: runnerResults.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { message: "Configure the run above and press Run." }) : /* @__PURE__ */ jsxRuntimeExports.jsx("table", { className: "w-full text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: runnerResults.map((r, idx) =>
|
|
54216
|
-
"
|
|
54217
|
-
|
|
54218
|
-
|
|
54219
|
-
|
|
54220
|
-
|
|
54221
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("
|
|
54222
|
-
|
|
54223
|
-
|
|
54224
|
-
|
|
54225
|
-
|
|
54226
|
-
|
|
54227
|
-
|
|
55293
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: runnerResults.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(EmptyState, { message: "Configure the run above and press Run." }) : /* @__PURE__ */ jsxRuntimeExports.jsx("table", { className: "w-full text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: runnerResults.map((r, idx) => {
|
|
55294
|
+
const scopeKey = (r.scopePath ?? []).join(" / ");
|
|
55295
|
+
const prevScope = idx > 0 ? (runnerResults[idx - 1].scopePath ?? []).join(" / ") : null;
|
|
55296
|
+
const showHeading = scopeKey !== "" && scopeKey !== prevScope;
|
|
55297
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(reactExports.Fragment, { children: [
|
|
55298
|
+
showHeading && /* @__PURE__ */ jsxRuntimeExports.jsx("tr", { className: "bg-surface-800/40", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("td", { colSpan: 6, className: "px-4 py-1.5 text-[10px] uppercase tracking-wider font-semibold text-surface-400", children: [
|
|
55299
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600", children: "▸ " }),
|
|
55300
|
+
scopeKey
|
|
55301
|
+
] }) }),
|
|
55302
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
55303
|
+
"tr",
|
|
55304
|
+
{
|
|
55305
|
+
className: `border-b border-surface-800/50 hover:bg-surface-800/30 ${r.isHook ? "opacity-80" : ""}`,
|
|
55306
|
+
children: [
|
|
55307
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-4 py-2 w-6", children: /* @__PURE__ */ jsxRuntimeExports.jsx(StatusDot, { status: r.status }) }),
|
|
55308
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-2 pr-2 w-20", children: r.isHook && r.hookType ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[9px] font-bold px-1.5 py-0.5 rounded uppercase tracking-wide whitespace-nowrap ${HOOK_BADGE[r.hookType]?.cls ?? ""}`, children: HOOK_BADGE[r.hookType]?.label }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-bold ${getMethodColor(r.method)}`, children: r.method }) }),
|
|
55309
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("td", { className: "py-2 pr-2", children: [
|
|
55310
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `truncate max-w-[260px] ${r.isHook ? "text-surface-400 italic" : "text-[var(--text-primary)]"}`, children: [
|
|
55311
|
+
r.name,
|
|
55312
|
+
r.iterationLabel && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-1.5 text-[10px] text-surface-500 font-mono", children: [
|
|
55313
|
+
"#",
|
|
55314
|
+
r.iterationLabel
|
|
55315
|
+
] })
|
|
55316
|
+
] }),
|
|
55317
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] text-surface-500 font-mono truncate max-w-[260px]", children: r.resolvedUrl })
|
|
55318
|
+
] }),
|
|
55319
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-2 pr-2 text-right text-surface-400 w-20", children: r.httpStatus ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `font-mono ${r.httpStatus < 400 ? "text-emerald-400" : "text-red-400"}`, children: r.httpStatus }) : r.error ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-400 text-[10px]", children: "error" }) : null }),
|
|
55320
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "py-2 pr-4 text-right w-16 text-surface-400", children: r.durationMs !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
55321
|
+
r.durationMs,
|
|
55322
|
+
"ms"
|
|
55323
|
+
] }) }),
|
|
55324
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("td", { className: "py-2 pr-4 w-24", children: [
|
|
55325
|
+
r.testResults && r.testResults.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: `text-[10px] ${r.testResults.every((t2) => t2.passed) ? "text-emerald-400" : "text-red-400"}`, children: [
|
|
55326
|
+
r.testResults.filter((t2) => t2.passed).length,
|
|
55327
|
+
"/",
|
|
55328
|
+
r.testResults.length,
|
|
55329
|
+
" tests"
|
|
55330
|
+
] }),
|
|
55331
|
+
r.error && !r.error.startsWith("Skipped") && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-orange-400", title: r.error, children: [
|
|
55332
|
+
"⚠ ",
|
|
55333
|
+
r.error.slice(0, 30)
|
|
55334
|
+
] }),
|
|
55335
|
+
r.error?.startsWith("Skipped") && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-surface-500 italic", children: "skipped" })
|
|
54228
55336
|
] })
|
|
54229
|
-
]
|
|
54230
|
-
|
|
54231
|
-
|
|
54232
|
-
|
|
54233
|
-
|
|
54234
|
-
r.durationMs,
|
|
54235
|
-
"ms"
|
|
54236
|
-
] }) }),
|
|
54237
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("td", { className: "py-2 pr-4 w-24", children: [
|
|
54238
|
-
r.testResults && r.testResults.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: `text-[10px] ${r.testResults.every((t2) => t2.passed) ? "text-emerald-400" : "text-red-400"}`, children: [
|
|
54239
|
-
r.testResults.filter((t2) => t2.passed).length,
|
|
54240
|
-
"/",
|
|
54241
|
-
r.testResults.length,
|
|
54242
|
-
" tests"
|
|
54243
|
-
] }),
|
|
54244
|
-
r.error && !r.error.startsWith("Skipped") && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-orange-400", title: r.error, children: [
|
|
54245
|
-
"⚠ ",
|
|
54246
|
-
r.error.slice(0, 30)
|
|
54247
|
-
] }),
|
|
54248
|
-
r.error?.startsWith("Skipped") && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-surface-500 italic", children: "skipped" })
|
|
54249
|
-
] })
|
|
54250
|
-
]
|
|
54251
|
-
},
|
|
54252
|
-
idx
|
|
54253
|
-
)) }) }) }),
|
|
55337
|
+
]
|
|
55338
|
+
}
|
|
55339
|
+
)
|
|
55340
|
+
] }, idx);
|
|
55341
|
+
}) }) }) }),
|
|
54254
55342
|
summary && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 px-4 py-2 border-t border-surface-800 bg-surface-800/30 flex-shrink-0 text-xs", children: [
|
|
54255
55343
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-emerald-400 font-medium", children: [
|
|
54256
55344
|
summary.passed,
|
|
@@ -54264,6 +55352,10 @@ function RunnerModal() {
|
|
|
54264
55352
|
summary.errors,
|
|
54265
55353
|
" errors"
|
|
54266
55354
|
] }),
|
|
55355
|
+
summary.skipped > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-400 font-medium", title: "Requests with no assertions to verify", children: [
|
|
55356
|
+
summary.skipped,
|
|
55357
|
+
" no tests"
|
|
55358
|
+
] }),
|
|
54267
55359
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-400", children: [
|
|
54268
55360
|
summary.total,
|
|
54269
55361
|
" total · ",
|
|
@@ -56855,6 +57947,9 @@ function App() {
|
|
|
56855
57947
|
const activeTabId = useStore((s) => s.activeTabId);
|
|
56856
57948
|
const setActiveTabId = useStore((s) => s.setActiveTabId);
|
|
56857
57949
|
const closeTab = useStore((s) => s.closeTab);
|
|
57950
|
+
const closeAllTabs = useStore((s) => s.closeAllTabs);
|
|
57951
|
+
const closeOtherTabs = useStore((s) => s.closeOtherTabs);
|
|
57952
|
+
const [tabContextMenu, setTabContextMenu] = reactExports.useState(null);
|
|
56858
57953
|
const showGeneratorPanel = useStore((s) => s.showGeneratorPanel);
|
|
56859
57954
|
const sidebarTab = useStore((s) => s.sidebarTab);
|
|
56860
57955
|
const setSidebarTab = useStore((s) => s.setSidebarTab);
|
|
@@ -56873,7 +57968,7 @@ function App() {
|
|
|
56873
57968
|
const setWsStatus = useStore((s) => s.setWsStatus);
|
|
56874
57969
|
const addWsMessage = useStore((s) => s.addWsMessage);
|
|
56875
57970
|
const [sidebarOpen, setSidebarOpen] = reactExports.useState(true);
|
|
56876
|
-
const [responseOpen, setResponseOpen] = reactExports.useState(
|
|
57971
|
+
const [responseOpen, setResponseOpen] = reactExports.useState(false);
|
|
56877
57972
|
const [docsModalOpen, setDocsModalOpen] = reactExports.useState(false);
|
|
56878
57973
|
const [sidebarWidth, setSidebarWidth] = reactExports.useState(256);
|
|
56879
57974
|
const [requestPaneWidth, setRequestPaneWidth] = reactExports.useState(null);
|
|
@@ -56940,6 +58035,9 @@ function App() {
|
|
|
56940
58035
|
}, [theme2]);
|
|
56941
58036
|
const activeTab = tabs.find((t2) => t2.id === activeTabId) ?? null;
|
|
56942
58037
|
const activeRequest = activeTab?.requestId ? Object.values(collections).find((c) => c.data.requests[activeTab.requestId])?.data.requests[activeTab.requestId] : null;
|
|
58038
|
+
reactExports.useEffect(() => {
|
|
58039
|
+
setResponseOpen(Boolean(activeTab?.lastResponse));
|
|
58040
|
+
}, [activeTabId, activeTab?.lastResponse]);
|
|
56943
58041
|
function selectPanel(tab) {
|
|
56944
58042
|
if (sidebarTab === tab && sidebarOpen) {
|
|
56945
58043
|
setSidebarOpen(false);
|
|
@@ -56957,7 +58055,7 @@ function App() {
|
|
|
56957
58055
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "#6aa3c8" }, children: "Spector" }),
|
|
56958
58056
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-2 text-[10px] font-normal opacity-50", children: [
|
|
56959
58057
|
"v",
|
|
56960
|
-
"0.
|
|
58058
|
+
"0.2.0"
|
|
56961
58059
|
] }),
|
|
56962
58060
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mx-2 opacity-30", children: "·" }),
|
|
56963
58061
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -57071,34 +58169,105 @@ function App() {
|
|
|
57071
58169
|
}
|
|
57072
58170
|
),
|
|
57073
58171
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "flex-1 min-w-0 flex flex-col min-h-0", children: [
|
|
57074
|
-
tabs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.
|
|
57075
|
-
|
|
57076
|
-
|
|
57077
|
-
|
|
58172
|
+
tabs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center border-b border-surface-800 bg-surface-950 flex-shrink-0", children: [
|
|
58173
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center overflow-x-auto flex-1 min-w-0", children: tabs.map((tab) => {
|
|
58174
|
+
const req = tab.requestId ? Object.values(collections).find((c) => c.data.requests[tab.requestId])?.data.requests[tab.requestId] : null;
|
|
58175
|
+
const isActive = tab.id === activeTabId;
|
|
58176
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
58177
|
+
"div",
|
|
58178
|
+
{
|
|
58179
|
+
onClick: () => setActiveTabId(tab.id),
|
|
58180
|
+
onContextMenu: (e) => {
|
|
58181
|
+
e.preventDefault();
|
|
58182
|
+
setTabContextMenu({ x: e.clientX, y: e.clientY, tabId: tab.id });
|
|
58183
|
+
},
|
|
58184
|
+
className: `group flex items-center gap-1.5 px-3 py-1.5 border-r border-surface-800 cursor-pointer min-w-0 max-w-[200px] flex-shrink-0 transition-colors ${isActive ? "bg-surface-900 border-b-2 border-b-blue-500 -mb-px" : "hover:bg-surface-900/50 text-surface-600"}`,
|
|
58185
|
+
children: [
|
|
58186
|
+
req && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-bold shrink-0 ${TAB_METHOD_COLORS[req.method] ?? "text-gray-400"}`, children: req.method }),
|
|
58187
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-xs truncate ${isActive ? "text-white" : ""}`, children: req?.name ?? "Untitled" }),
|
|
58188
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
58189
|
+
"button",
|
|
58190
|
+
{
|
|
58191
|
+
onClick: (e) => {
|
|
58192
|
+
e.stopPropagation();
|
|
58193
|
+
closeTab(tab.id);
|
|
58194
|
+
},
|
|
58195
|
+
className: "ml-auto opacity-0 group-hover:opacity-100 shrink-0 text-surface-600 hover:text-white transition-all leading-none",
|
|
58196
|
+
title: "Close tab",
|
|
58197
|
+
children: "×"
|
|
58198
|
+
}
|
|
58199
|
+
)
|
|
58200
|
+
]
|
|
58201
|
+
},
|
|
58202
|
+
tab.id
|
|
58203
|
+
);
|
|
58204
|
+
}) }),
|
|
58205
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
58206
|
+
"button",
|
|
58207
|
+
{
|
|
58208
|
+
onClick: closeAllTabs,
|
|
58209
|
+
title: "Close all tabs",
|
|
58210
|
+
className: "flex-shrink-0 px-2 py-1.5 text-surface-500 hover:text-white hover:bg-surface-900/50 border-l border-surface-800 text-xs leading-none transition-colors",
|
|
58211
|
+
children: "⨯ all"
|
|
58212
|
+
}
|
|
58213
|
+
)
|
|
58214
|
+
] }),
|
|
58215
|
+
tabContextMenu && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
58216
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
58217
|
+
"div",
|
|
58218
|
+
{
|
|
58219
|
+
className: "fixed inset-0 z-40",
|
|
58220
|
+
onClick: () => setTabContextMenu(null),
|
|
58221
|
+
onContextMenu: (e) => {
|
|
58222
|
+
e.preventDefault();
|
|
58223
|
+
setTabContextMenu(null);
|
|
58224
|
+
}
|
|
58225
|
+
}
|
|
58226
|
+
),
|
|
58227
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
57078
58228
|
"div",
|
|
57079
58229
|
{
|
|
57080
|
-
|
|
57081
|
-
|
|
58230
|
+
className: "fixed z-50 bg-surface-900 border border-surface-700 rounded shadow-2xl py-1 text-xs min-w-[160px]",
|
|
58231
|
+
style: { left: tabContextMenu.x, top: tabContextMenu.y },
|
|
57082
58232
|
children: [
|
|
57083
|
-
req && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-bold shrink-0 ${TAB_METHOD_COLORS[req.method] ?? "text-gray-400"}`, children: req.method }),
|
|
57084
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-xs truncate ${isActive ? "text-white" : ""}`, children: req?.name ?? "Untitled" }),
|
|
57085
58233
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
57086
58234
|
"button",
|
|
57087
58235
|
{
|
|
57088
|
-
onClick: (
|
|
57089
|
-
|
|
57090
|
-
|
|
58236
|
+
onClick: () => {
|
|
58237
|
+
closeTab(tabContextMenu.tabId);
|
|
58238
|
+
setTabContextMenu(null);
|
|
57091
58239
|
},
|
|
57092
|
-
className: "
|
|
57093
|
-
|
|
57094
|
-
|
|
58240
|
+
className: "w-full text-left px-3 py-1.5 text-surface-300 hover:bg-surface-800 hover:text-white transition-colors",
|
|
58241
|
+
children: "Close"
|
|
58242
|
+
}
|
|
58243
|
+
),
|
|
58244
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
58245
|
+
"button",
|
|
58246
|
+
{
|
|
58247
|
+
onClick: () => {
|
|
58248
|
+
closeOtherTabs(tabContextMenu.tabId);
|
|
58249
|
+
setTabContextMenu(null);
|
|
58250
|
+
},
|
|
58251
|
+
disabled: tabs.length < 2,
|
|
58252
|
+
className: "w-full text-left px-3 py-1.5 text-surface-300 hover:bg-surface-800 hover:text-white disabled:text-surface-600 disabled:hover:bg-transparent transition-colors",
|
|
58253
|
+
children: "Close others"
|
|
58254
|
+
}
|
|
58255
|
+
),
|
|
58256
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
58257
|
+
"button",
|
|
58258
|
+
{
|
|
58259
|
+
onClick: () => {
|
|
58260
|
+
closeAllTabs();
|
|
58261
|
+
setTabContextMenu(null);
|
|
58262
|
+
},
|
|
58263
|
+
className: "w-full text-left px-3 py-1.5 text-surface-300 hover:bg-surface-800 hover:text-white transition-colors",
|
|
58264
|
+
children: "Close all"
|
|
57095
58265
|
}
|
|
57096
58266
|
)
|
|
57097
58267
|
]
|
|
57098
|
-
}
|
|
57099
|
-
|
|
57100
|
-
|
|
57101
|
-
}) }),
|
|
58268
|
+
}
|
|
58269
|
+
)
|
|
58270
|
+
] }),
|
|
57102
58271
|
sidebarTab === "contracts" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ContractResultsPanel, {}) }) : sidebarTab === "mocks" && recorderRunning ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
57103
58272
|
RecorderPanel,
|
|
57104
58273
|
{
|