@testsmith/api-spector 0.6.2 → 0.6.4
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/agents.js +5 -5
- package/out/main/chunks/{broker-client-WEymdqAK.js → broker-client-CvRuiX3o.js} +26 -23
- package/out/main/chunks/{cli-common-vASoDfQH.js → cli-common-Cq_cphpZ.js} +4 -4
- package/out/main/chunks/{coverage-C54mZEh_.js → coverage-C0U4QM83.js} +8 -10
- package/out/main/chunks/{data-files-Br2h3Dt2.js → data-files-BYqhsoPe.js} +4 -4
- package/out/main/chunks/escape-DDVAlOvZ.js +9 -0
- package/out/main/chunks/{import-DdXhO56X.js → import-DYssQzex.js} +4 -4
- package/out/main/chunks/{mock-server-BxiXhP1m.js → mock-server-C4kTFkod.js} +9 -11
- package/out/main/chunks/{recorder-0Ij921El.js → recorder-BkO8G_mB.js} +2 -2
- package/out/main/chunks/{request-collection-Hqh3I3rs.js → request-collection-KGPuvN7o.js} +5 -4
- package/out/main/chunks/{request-exec-DAFA6Fap.js → request-exec-BRmVweue.js} +41 -41
- package/out/main/chunks/{soap-handler-BAPCALkN.js → soap-handler-BznuMFIP.js} +7 -9
- package/out/main/compare.js +10 -10
- package/out/main/contract.js +18 -20
- package/out/main/coverage.js +7 -7
- package/out/main/generate-tests.js +9 -9
- package/out/main/index.js +166 -263
- package/out/main/lib.js +6 -7
- package/out/main/mock.js +8 -8
- package/out/main/record.js +9 -9
- package/out/main/runner.js +50 -22
- package/out/main/wsdl.js +9 -9
- package/out/preload/index.js +1 -1
- package/out/renderer/assets/{GraphQLEditor-DtppmZJO.js → GraphQLEditor-Bih8eb_r.js} +6 -6
- package/out/renderer/assets/{SoapEditor-BwSm12wH.js → SoapEditor-D1sQKu7l.js} +3 -3
- package/out/renderer/assets/{index-D6-zmXen.js → index-vEDOfWlE.js} +418 -279
- package/out/renderer/index.html +1 -1
- package/package.json +1 -1
- package/out/main/chunks/escape-BwPM4Tf6.js +0 -9
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./GraphQLEditor-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./GraphQLEditor-Bih8eb_r.js","./codemirror-F6m3Hm1M.js","./ajv-2MAg6kGF.js","./SoapEditor-D1sQKu7l.js"])))=>i.map(i=>d[i]);
|
|
2
2
|
import { r as reactExports, g as getDefaultExportFromCjs, R as React$2, a as autocompletion, h as hoverTooltip, j as jsxRuntimeExports, k as keymap, t as toggleComment, x as xml, b as json, c as ReactCodeMirror, o as oneDark, d as javascript } from "./codemirror-F6m3Hm1M.js";
|
|
3
3
|
import { A as Ajv } from "./ajv-2MAg6kGF.js";
|
|
4
4
|
var client = { exports: {} };
|
|
@@ -12797,132 +12797,6 @@ const immerImpl = (initializer) => (set2, get2, store) => {
|
|
|
12797
12797
|
return initializer(store.setState, get2, store);
|
|
12798
12798
|
};
|
|
12799
12799
|
const immer = immerImpl;
|
|
12800
|
-
function uniqueName(base, existing) {
|
|
12801
|
-
if (!existing.includes(base)) return base;
|
|
12802
|
-
let i = 2;
|
|
12803
|
-
while (existing.includes(`${base} (${i})`)) i++;
|
|
12804
|
-
return `${base} (${i})`;
|
|
12805
|
-
}
|
|
12806
|
-
function colRelPath(name, id) {
|
|
12807
|
-
const safe = safeName(name) || id.slice(0, 8);
|
|
12808
|
-
return `collections/${safe}.spector`;
|
|
12809
|
-
}
|
|
12810
|
-
function envRelPath(name, id) {
|
|
12811
|
-
const safe = safeName(name) || id;
|
|
12812
|
-
return `environments/${safe}.env.json`;
|
|
12813
|
-
}
|
|
12814
|
-
function safeName(name) {
|
|
12815
|
-
return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-_]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
12816
|
-
}
|
|
12817
|
-
let getRandomValues;
|
|
12818
|
-
const rnds8 = new Uint8Array(16);
|
|
12819
|
-
function rng() {
|
|
12820
|
-
if (!getRandomValues) {
|
|
12821
|
-
getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
|
|
12822
|
-
if (!getRandomValues) {
|
|
12823
|
-
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
|
12824
|
-
}
|
|
12825
|
-
}
|
|
12826
|
-
return getRandomValues(rnds8);
|
|
12827
|
-
}
|
|
12828
|
-
const byteToHex = [];
|
|
12829
|
-
for (let i = 0; i < 256; ++i) {
|
|
12830
|
-
byteToHex.push((i + 256).toString(16).slice(1));
|
|
12831
|
-
}
|
|
12832
|
-
function unsafeStringify(arr, offset = 0) {
|
|
12833
|
-
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
|
12834
|
-
}
|
|
12835
|
-
const randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
12836
|
-
const native = {
|
|
12837
|
-
randomUUID
|
|
12838
|
-
};
|
|
12839
|
-
function v4(options, buf, offset) {
|
|
12840
|
-
if (native.randomUUID && true && !options) {
|
|
12841
|
-
return native.randomUUID();
|
|
12842
|
-
}
|
|
12843
|
-
options = options || {};
|
|
12844
|
-
const rnds = options.random || (options.rng || rng)();
|
|
12845
|
-
rnds[6] = rnds[6] & 15 | 64;
|
|
12846
|
-
rnds[8] = rnds[8] & 63 | 128;
|
|
12847
|
-
return unsafeStringify(rnds);
|
|
12848
|
-
}
|
|
12849
|
-
function orderedChildren(folder2) {
|
|
12850
|
-
const reqSet = new Set(folder2.requestIds);
|
|
12851
|
-
const folderSet = new Set(folder2.folders.map((f) => f.id));
|
|
12852
|
-
const seen2 = /* @__PURE__ */ new Set();
|
|
12853
|
-
const out = [];
|
|
12854
|
-
for (const ref of folder2.childOrder ?? []) {
|
|
12855
|
-
const key = `${ref.type}:${ref.id}`;
|
|
12856
|
-
if (seen2.has(key)) continue;
|
|
12857
|
-
if (ref.type === "request" && reqSet.has(ref.id) || ref.type === "folder" && folderSet.has(ref.id)) {
|
|
12858
|
-
out.push({ type: ref.type, id: ref.id });
|
|
12859
|
-
seen2.add(key);
|
|
12860
|
-
}
|
|
12861
|
-
}
|
|
12862
|
-
for (const id of folder2.requestIds) if (!seen2.has(`request:${id}`)) out.push({ type: "request", id });
|
|
12863
|
-
for (const f of folder2.folders) if (!seen2.has(`folder:${f.id}`)) out.push({ type: "folder", id: f.id });
|
|
12864
|
-
return out;
|
|
12865
|
-
}
|
|
12866
|
-
function findFolder$1(root2, id) {
|
|
12867
|
-
if (root2.id === id) return root2;
|
|
12868
|
-
for (const sub of root2.folders) {
|
|
12869
|
-
const found = findFolder$1(sub, id);
|
|
12870
|
-
if (found) return found;
|
|
12871
|
-
}
|
|
12872
|
-
return null;
|
|
12873
|
-
}
|
|
12874
|
-
function findFolderContaining(root2, reqId) {
|
|
12875
|
-
if (root2.requestIds.includes(reqId)) return root2;
|
|
12876
|
-
for (const sub of root2.folders) {
|
|
12877
|
-
const found = findFolderContaining(sub, reqId);
|
|
12878
|
-
if (found) return found;
|
|
12879
|
-
}
|
|
12880
|
-
return null;
|
|
12881
|
-
}
|
|
12882
|
-
function removeFromFolder(root2, reqId) {
|
|
12883
|
-
root2.requestIds = root2.requestIds.filter((id) => id !== reqId);
|
|
12884
|
-
root2.folders.forEach((sub) => removeFromFolder(sub, reqId));
|
|
12885
|
-
}
|
|
12886
|
-
function removeFolderById(parent, folderId) {
|
|
12887
|
-
const idx = parent.folders.findIndex((f) => f.id === folderId);
|
|
12888
|
-
if (idx !== -1) {
|
|
12889
|
-
parent.folders.splice(idx, 1);
|
|
12890
|
-
return true;
|
|
12891
|
-
}
|
|
12892
|
-
for (const sub of parent.folders) {
|
|
12893
|
-
if (removeFolderById(sub, folderId)) return true;
|
|
12894
|
-
}
|
|
12895
|
-
return false;
|
|
12896
|
-
}
|
|
12897
|
-
function findFolderParent(root2, folderId) {
|
|
12898
|
-
for (const sub of root2.folders) {
|
|
12899
|
-
if (sub.id === folderId) return root2;
|
|
12900
|
-
const found = findFolderParent(sub, folderId);
|
|
12901
|
-
if (found) return found;
|
|
12902
|
-
}
|
|
12903
|
-
return null;
|
|
12904
|
-
}
|
|
12905
|
-
function findFolderPath(root2, requestId) {
|
|
12906
|
-
if (root2.requestIds.includes(requestId)) return [root2];
|
|
12907
|
-
for (const sub of root2.folders) {
|
|
12908
|
-
const path = findFolderPath(sub, requestId);
|
|
12909
|
-
if (path.length > 0) return [root2, ...path];
|
|
12910
|
-
}
|
|
12911
|
-
return [];
|
|
12912
|
-
}
|
|
12913
|
-
function collectRequestIds$1(f) {
|
|
12914
|
-
return [...f.requestIds, ...f.folders.flatMap(collectRequestIds$1)];
|
|
12915
|
-
}
|
|
12916
|
-
function reIdFolderTree(root2, mapRequestId) {
|
|
12917
|
-
root2.id = v4();
|
|
12918
|
-
root2.requestIds = root2.requestIds.map(mapRequestId);
|
|
12919
|
-
root2.folders.forEach((sub) => reIdFolderTree(sub, mapRequestId));
|
|
12920
|
-
}
|
|
12921
|
-
function cloneAndReId(folder2, mapRequestId) {
|
|
12922
|
-
const cloned = JSON.parse(JSON.stringify(folder2));
|
|
12923
|
-
reIdFolderTree(cloned, mapRequestId);
|
|
12924
|
-
return cloned;
|
|
12925
|
-
}
|
|
12926
12800
|
const WS_MESSAGE_CAP = 1e3;
|
|
12927
12801
|
const createWsSlice = (set2) => ({
|
|
12928
12802
|
wsConnections: {},
|
|
@@ -12988,7 +12862,7 @@ const createStreamSlice = (set2) => ({
|
|
|
12988
12862
|
s.liveStream = { streamId, tabId, events: [], streaming: true };
|
|
12989
12863
|
}),
|
|
12990
12864
|
pushLiveStreamEvents: (streamId, events) => set2((s) => {
|
|
12991
|
-
if (
|
|
12865
|
+
if (s.liveStream?.streamId !== streamId) return;
|
|
12992
12866
|
s.liveStream.events.push(...events);
|
|
12993
12867
|
const overflow = s.liveStream.events.length - LIVE_EVENT_CAP;
|
|
12994
12868
|
if (overflow > 0) s.liveStream.events.splice(0, overflow);
|
|
@@ -13088,7 +12962,7 @@ const createContractSlice = (set2) => ({
|
|
|
13088
12962
|
loadContractSnapshot: (relPath, snapshot) => set2((s) => {
|
|
13089
12963
|
s.contractSnapshots[relPath] = snapshot;
|
|
13090
12964
|
if (s.workspace) {
|
|
13091
|
-
|
|
12965
|
+
s.workspace.contracts ??= [];
|
|
13092
12966
|
if (!s.workspace.contracts.includes(relPath)) s.workspace.contracts.push(relPath);
|
|
13093
12967
|
}
|
|
13094
12968
|
}),
|
|
@@ -13111,6 +12985,38 @@ const createContractSlice = (set2) => ({
|
|
|
13111
12985
|
s.contractDesignerSeed = null;
|
|
13112
12986
|
})
|
|
13113
12987
|
});
|
|
12988
|
+
let getRandomValues;
|
|
12989
|
+
const rnds8 = new Uint8Array(16);
|
|
12990
|
+
function rng() {
|
|
12991
|
+
if (!getRandomValues) {
|
|
12992
|
+
getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
|
|
12993
|
+
if (!getRandomValues) {
|
|
12994
|
+
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
|
12995
|
+
}
|
|
12996
|
+
}
|
|
12997
|
+
return getRandomValues(rnds8);
|
|
12998
|
+
}
|
|
12999
|
+
const byteToHex = [];
|
|
13000
|
+
for (let i = 0; i < 256; ++i) {
|
|
13001
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
13002
|
+
}
|
|
13003
|
+
function unsafeStringify(arr, offset = 0) {
|
|
13004
|
+
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
|
13005
|
+
}
|
|
13006
|
+
const randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
13007
|
+
const native = {
|
|
13008
|
+
randomUUID
|
|
13009
|
+
};
|
|
13010
|
+
function v4(options, buf, offset) {
|
|
13011
|
+
if (native.randomUUID && true && !options) {
|
|
13012
|
+
return native.randomUUID();
|
|
13013
|
+
}
|
|
13014
|
+
options = options || {};
|
|
13015
|
+
const rnds = options.random || (options.rng || rng)();
|
|
13016
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
13017
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
13018
|
+
return unsafeStringify(rnds);
|
|
13019
|
+
}
|
|
13114
13020
|
function makeTab(requestId, collectionId, opts = {}) {
|
|
13115
13021
|
return {
|
|
13116
13022
|
id: v4(),
|
|
@@ -13241,6 +13147,100 @@ const createTabsSlice = (set2, get2) => ({
|
|
|
13241
13147
|
if (tab) tab.requestTab = t;
|
|
13242
13148
|
})
|
|
13243
13149
|
});
|
|
13150
|
+
function uniqueName(base, existing) {
|
|
13151
|
+
if (!existing.includes(base)) return base;
|
|
13152
|
+
let i = 2;
|
|
13153
|
+
while (existing.includes(`${base} (${i})`)) i++;
|
|
13154
|
+
return `${base} (${i})`;
|
|
13155
|
+
}
|
|
13156
|
+
function colRelPath(name, id) {
|
|
13157
|
+
const safe = safeName(name) || id.slice(0, 8);
|
|
13158
|
+
return `collections/${safe}.spector`;
|
|
13159
|
+
}
|
|
13160
|
+
function envRelPath(name, id) {
|
|
13161
|
+
const safe = safeName(name) || id;
|
|
13162
|
+
return `environments/${safe}.env.json`;
|
|
13163
|
+
}
|
|
13164
|
+
function safeName(name) {
|
|
13165
|
+
return name.trim().toLowerCase().replaceAll(/\s+/g, "-").replaceAll(/[^a-z0-9-_]/g, "").replaceAll(/-+/g, "-").replaceAll(/^-|-$/g, "");
|
|
13166
|
+
}
|
|
13167
|
+
function orderedChildren(folder2) {
|
|
13168
|
+
const reqSet = new Set(folder2.requestIds);
|
|
13169
|
+
const folderSet = new Set(folder2.folders.map((f) => f.id));
|
|
13170
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
13171
|
+
const out = [];
|
|
13172
|
+
for (const ref of folder2.childOrder ?? []) {
|
|
13173
|
+
const key = `${ref.type}:${ref.id}`;
|
|
13174
|
+
if (seen2.has(key)) continue;
|
|
13175
|
+
if (ref.type === "request" && reqSet.has(ref.id) || ref.type === "folder" && folderSet.has(ref.id)) {
|
|
13176
|
+
out.push({ type: ref.type, id: ref.id });
|
|
13177
|
+
seen2.add(key);
|
|
13178
|
+
}
|
|
13179
|
+
}
|
|
13180
|
+
for (const id of folder2.requestIds) if (!seen2.has(`request:${id}`)) out.push({ type: "request", id });
|
|
13181
|
+
for (const f of folder2.folders) if (!seen2.has(`folder:${f.id}`)) out.push({ type: "folder", id: f.id });
|
|
13182
|
+
return out;
|
|
13183
|
+
}
|
|
13184
|
+
function findFolder$1(root2, id) {
|
|
13185
|
+
if (root2.id === id) return root2;
|
|
13186
|
+
for (const sub of root2.folders) {
|
|
13187
|
+
const found = findFolder$1(sub, id);
|
|
13188
|
+
if (found) return found;
|
|
13189
|
+
}
|
|
13190
|
+
return null;
|
|
13191
|
+
}
|
|
13192
|
+
function findFolderContaining(root2, reqId) {
|
|
13193
|
+
if (root2.requestIds.includes(reqId)) return root2;
|
|
13194
|
+
for (const sub of root2.folders) {
|
|
13195
|
+
const found = findFolderContaining(sub, reqId);
|
|
13196
|
+
if (found) return found;
|
|
13197
|
+
}
|
|
13198
|
+
return null;
|
|
13199
|
+
}
|
|
13200
|
+
function removeFromFolder(root2, reqId) {
|
|
13201
|
+
root2.requestIds = root2.requestIds.filter((id) => id !== reqId);
|
|
13202
|
+
root2.folders.forEach((sub) => removeFromFolder(sub, reqId));
|
|
13203
|
+
}
|
|
13204
|
+
function removeFolderById(parent, folderId) {
|
|
13205
|
+
const idx = parent.folders.findIndex((f) => f.id === folderId);
|
|
13206
|
+
if (idx !== -1) {
|
|
13207
|
+
parent.folders.splice(idx, 1);
|
|
13208
|
+
return true;
|
|
13209
|
+
}
|
|
13210
|
+
for (const sub of parent.folders) {
|
|
13211
|
+
if (removeFolderById(sub, folderId)) return true;
|
|
13212
|
+
}
|
|
13213
|
+
return false;
|
|
13214
|
+
}
|
|
13215
|
+
function findFolderParent(root2, folderId) {
|
|
13216
|
+
for (const sub of root2.folders) {
|
|
13217
|
+
if (sub.id === folderId) return root2;
|
|
13218
|
+
const found = findFolderParent(sub, folderId);
|
|
13219
|
+
if (found) return found;
|
|
13220
|
+
}
|
|
13221
|
+
return null;
|
|
13222
|
+
}
|
|
13223
|
+
function findFolderPath(root2, requestId) {
|
|
13224
|
+
if (root2.requestIds.includes(requestId)) return [root2];
|
|
13225
|
+
for (const sub of root2.folders) {
|
|
13226
|
+
const path = findFolderPath(sub, requestId);
|
|
13227
|
+
if (path.length > 0) return [root2, ...path];
|
|
13228
|
+
}
|
|
13229
|
+
return [];
|
|
13230
|
+
}
|
|
13231
|
+
function collectRequestIds$1(f) {
|
|
13232
|
+
return [...f.requestIds, ...f.folders.flatMap(collectRequestIds$1)];
|
|
13233
|
+
}
|
|
13234
|
+
function reIdFolderTree(root2, mapRequestId) {
|
|
13235
|
+
root2.id = v4();
|
|
13236
|
+
root2.requestIds = root2.requestIds.map(mapRequestId);
|
|
13237
|
+
root2.folders.forEach((sub) => reIdFolderTree(sub, mapRequestId));
|
|
13238
|
+
}
|
|
13239
|
+
function cloneAndReId(folder2, mapRequestId) {
|
|
13240
|
+
const cloned = structuredClone(folder2);
|
|
13241
|
+
reIdFolderTree(cloned, mapRequestId);
|
|
13242
|
+
return cloned;
|
|
13243
|
+
}
|
|
13244
13244
|
const WRITE_METHODS$1 = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH"]);
|
|
13245
13245
|
function newId() {
|
|
13246
13246
|
try {
|
|
@@ -13250,7 +13250,7 @@ function newId() {
|
|
|
13250
13250
|
}
|
|
13251
13251
|
}
|
|
13252
13252
|
function clone(base, patch) {
|
|
13253
|
-
const copy2 =
|
|
13253
|
+
const copy2 = structuredClone(base);
|
|
13254
13254
|
copy2.id = newId();
|
|
13255
13255
|
delete copy2.examples;
|
|
13256
13256
|
delete copy2.contract;
|
|
@@ -13482,8 +13482,8 @@ const createCollectionsSlice = (set2, get2) => ({
|
|
|
13482
13482
|
s.tabs = s.tabs.filter((t) => t.collectionId !== id);
|
|
13483
13483
|
if (s.activeCollectionId === id) {
|
|
13484
13484
|
s.activeCollectionId = Object.keys(s.collections)[0] ?? null;
|
|
13485
|
-
const
|
|
13486
|
-
if (!
|
|
13485
|
+
const hasActiveTab = s.tabs.some((t) => t.id === s.activeTabId);
|
|
13486
|
+
if (!hasActiveTab) s.activeTabId = s.tabs[0]?.id ?? null;
|
|
13487
13487
|
}
|
|
13488
13488
|
});
|
|
13489
13489
|
},
|
|
@@ -13629,7 +13629,7 @@ const createCollectionsSlice = (set2, get2) => ({
|
|
|
13629
13629
|
const entry = Object.values(s.collections).find((c) => c.data.requests[requestId]);
|
|
13630
13630
|
const ex = entry?.data.requests[requestId].examples?.find((e) => e.id === exampleId);
|
|
13631
13631
|
if (!entry || !ex) return;
|
|
13632
|
-
ex.request = { ...ex.request
|
|
13632
|
+
ex.request = { ...ex.request, ...patch };
|
|
13633
13633
|
entry.dirty = true;
|
|
13634
13634
|
}),
|
|
13635
13635
|
updateExampleResponse: (requestId, exampleId, response) => set2((s) => {
|
|
@@ -13711,7 +13711,7 @@ const createCollectionsSlice = (set2, get2) => ({
|
|
|
13711
13711
|
}),
|
|
13712
13712
|
duplicateRequest: (collectionId, id) => set2((s) => {
|
|
13713
13713
|
const col = s.collections[collectionId]?.data;
|
|
13714
|
-
if (!col
|
|
13714
|
+
if (!col?.requests[id]) return;
|
|
13715
13715
|
const orig = col.requests[id];
|
|
13716
13716
|
const copy2 = { ...JSON.parse(JSON.stringify(orig)), id: v4(), name: orig.name + " (copy)" };
|
|
13717
13717
|
col.requests[copy2.id] = copy2;
|
|
@@ -13834,7 +13834,7 @@ const createCollectionsSlice = (set2, get2) => ({
|
|
|
13834
13834
|
const entry = Object.values(s.collections).find((c) => c.data.requests[requestId]);
|
|
13835
13835
|
if (!entry) return;
|
|
13836
13836
|
const req = entry.data.requests[requestId];
|
|
13837
|
-
req.meta = { ...req.meta
|
|
13837
|
+
req.meta = { ...req.meta, tags };
|
|
13838
13838
|
entry.dirty = true;
|
|
13839
13839
|
}),
|
|
13840
13840
|
// ── Folder settings ─────────────────────────────────────────────────────────
|
|
@@ -13882,7 +13882,7 @@ const STORAGE_KEYS = {
|
|
|
13882
13882
|
updateSkipped: "apiSpectorUpdateSkipped"
|
|
13883
13883
|
};
|
|
13884
13884
|
function envSlugRelPath(name) {
|
|
13885
|
-
return `environments/${name.toLowerCase().
|
|
13885
|
+
return `environments/${name.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-")}.env.json`;
|
|
13886
13886
|
}
|
|
13887
13887
|
const createEnvironmentsSlice = (set2, get2) => ({
|
|
13888
13888
|
environments: {},
|
|
@@ -13982,7 +13982,7 @@ const createMocksSlice = (set2, get2) => ({
|
|
|
13982
13982
|
s.mocks[mock.id] = { relPath, data: mock, running: false };
|
|
13983
13983
|
s.activeMockId = mock.id;
|
|
13984
13984
|
if (s.workspace) {
|
|
13985
|
-
|
|
13985
|
+
s.workspace.mocks ??= [];
|
|
13986
13986
|
s.workspace.mocks.push(relPath);
|
|
13987
13987
|
}
|
|
13988
13988
|
}),
|
|
@@ -14045,7 +14045,7 @@ const createUiSlice = (set2) => ({
|
|
|
14045
14045
|
s.theme = t;
|
|
14046
14046
|
localStorage.setItem(STORAGE_KEYS.theme, t);
|
|
14047
14047
|
if (s.workspace) {
|
|
14048
|
-
|
|
14048
|
+
s.workspace.settings ??= {};
|
|
14049
14049
|
s.workspace.settings.theme = t;
|
|
14050
14050
|
}
|
|
14051
14051
|
if (t === "system") {
|
|
@@ -14184,7 +14184,7 @@ const useStore = create()(
|
|
|
14184
14184
|
if (activeColId && s.collections[activeColId]) {
|
|
14185
14185
|
const col = s.collections[activeColId].data;
|
|
14186
14186
|
col.collectionVariables = {
|
|
14187
|
-
...col.collectionVariables
|
|
14187
|
+
...col.collectionVariables,
|
|
14188
14188
|
...safeColVars
|
|
14189
14189
|
};
|
|
14190
14190
|
s.collections[activeColId].dirty = true;
|
|
@@ -14972,7 +14972,7 @@ function useVarNames() {
|
|
|
14972
14972
|
}
|
|
14973
14973
|
const envVars = activeEnv?.variables ?? [];
|
|
14974
14974
|
envVars.filter((v) => v.enabled && v.key).forEach((v) => names.add(v.key));
|
|
14975
|
-
return [...DYNAMIC_VAR_NAMES, ...Array.from(names).sort()];
|
|
14975
|
+
return [...DYNAMIC_VAR_NAMES, ...Array.from(names).sort((a, b) => a.localeCompare(b))];
|
|
14976
14976
|
}, [
|
|
14977
14977
|
activeEnv,
|
|
14978
14978
|
activeCollectionId,
|
|
@@ -23837,7 +23837,7 @@ function detectLocale() {
|
|
|
23837
23837
|
}
|
|
23838
23838
|
function interpolate(str, vars) {
|
|
23839
23839
|
if (!vars) return str;
|
|
23840
|
-
return str.
|
|
23840
|
+
return str.replaceAll(/:([a-zA-Z][a-zA-Z0-9]*)/g, (m, k) => k in vars ? String(vars[k]) : m);
|
|
23841
23841
|
}
|
|
23842
23842
|
function translate(locale, key, vars) {
|
|
23843
23843
|
let msg = CATALOGS[locale]?.[key] ?? key;
|
|
@@ -23872,7 +23872,8 @@ function I18nProvider({ children }) {
|
|
|
23872
23872
|
setLocaleState(l);
|
|
23873
23873
|
}, []);
|
|
23874
23874
|
const t = reactExports.useCallback((key, vars) => translate(locale, key, vars), [locale]);
|
|
23875
|
-
|
|
23875
|
+
const ctx = reactExports.useMemo(() => ({ locale, setLocale, t }), [locale, setLocale, t]);
|
|
23876
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(I18nContext.Provider, { value: ctx, children });
|
|
23876
23877
|
}
|
|
23877
23878
|
function useT() {
|
|
23878
23879
|
return reactExports.useContext(I18nContext).t;
|
|
@@ -24359,18 +24360,34 @@ function Modal({
|
|
|
24359
24360
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
24360
24361
|
"div",
|
|
24361
24362
|
{
|
|
24363
|
+
role: closeOnBackdrop ? "button" : void 0,
|
|
24364
|
+
tabIndex: closeOnBackdrop ? -1 : void 0,
|
|
24365
|
+
"aria-label": closeOnBackdrop ? "Close dialog" : void 0,
|
|
24362
24366
|
className: `fixed inset-0 ${overlayClassName}`,
|
|
24363
|
-
onClick: closeOnBackdrop ?
|
|
24364
|
-
|
|
24365
|
-
|
|
24366
|
-
|
|
24367
|
-
|
|
24368
|
-
|
|
24369
|
-
|
|
24370
|
-
|
|
24371
|
-
|
|
24372
|
-
|
|
24373
|
-
|
|
24367
|
+
onClick: closeOnBackdrop ? (e) => {
|
|
24368
|
+
if (e.target === e.currentTarget) onClose();
|
|
24369
|
+
} : void 0,
|
|
24370
|
+
onKeyDown: closeOnBackdrop ? (e) => {
|
|
24371
|
+
if (e.key === "Escape") onClose();
|
|
24372
|
+
} : void 0,
|
|
24373
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
24374
|
+
"div",
|
|
24375
|
+
{
|
|
24376
|
+
role: "dialog",
|
|
24377
|
+
"aria-modal": "true",
|
|
24378
|
+
className: panelClassName,
|
|
24379
|
+
children: [
|
|
24380
|
+
title !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-4 py-2.5 border-b border-surface-800 flex-shrink-0", children: [
|
|
24381
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
24382
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-sm font-semibold", children: title }),
|
|
24383
|
+
subtitle !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-400 mt-0.5", children: subtitle })
|
|
24384
|
+
] }),
|
|
24385
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "text-surface-400 hover:text-[var(--text-primary)] text-lg leading-none", children: "×" })
|
|
24386
|
+
] }),
|
|
24387
|
+
children
|
|
24388
|
+
]
|
|
24389
|
+
}
|
|
24390
|
+
)
|
|
24374
24391
|
}
|
|
24375
24392
|
);
|
|
24376
24393
|
}
|
|
@@ -25053,7 +25070,7 @@ function normalisePath(url) {
|
|
|
25053
25070
|
let path = url.replace(/^\{\{[^}]+\}\}/, "").replace(/^https?:\/\/[^/]+/, "");
|
|
25054
25071
|
if (!path.startsWith("/")) path = "/" + path;
|
|
25055
25072
|
path = path.split("?")[0];
|
|
25056
|
-
path = path.
|
|
25073
|
+
path = path.replaceAll(/\{\{([^}]+)\}\}/g, "{$1}");
|
|
25057
25074
|
return path;
|
|
25058
25075
|
}
|
|
25059
25076
|
function collectRequestIds(folder2) {
|
|
@@ -25499,7 +25516,7 @@ function collectAllTags(folder2, requests) {
|
|
|
25499
25516
|
f.folders.forEach(walk2);
|
|
25500
25517
|
}
|
|
25501
25518
|
walk2(folder2);
|
|
25502
|
-
return Array.from(tags).sort();
|
|
25519
|
+
return Array.from(tags).sort((a, b) => a.localeCompare(b));
|
|
25503
25520
|
}
|
|
25504
25521
|
function folderPathTo(root2, requestId) {
|
|
25505
25522
|
if (root2.requestIds.includes(requestId)) return [root2];
|
|
@@ -25522,11 +25539,12 @@ function getHooksForRequest(requestId, collection2) {
|
|
|
25522
25539
|
before.push(...bAll, ...bEach);
|
|
25523
25540
|
afterReversed.push(...aEach, ...aAll);
|
|
25524
25541
|
}
|
|
25525
|
-
|
|
25542
|
+
afterReversed.reverse();
|
|
25543
|
+
return { before, after: afterReversed };
|
|
25526
25544
|
}
|
|
25527
25545
|
function authIsConfigured(auth) {
|
|
25528
25546
|
if (!auth || auth.type === "none") return false;
|
|
25529
|
-
const set2 = (s) => !!
|
|
25547
|
+
const set2 = (s) => !!s?.trim();
|
|
25530
25548
|
switch (auth.type) {
|
|
25531
25549
|
case "bearer":
|
|
25532
25550
|
return set2(auth.token) || set2(auth.tokenSecretRef);
|
|
@@ -25557,8 +25575,9 @@ function resolveInheritedAuthAndHeaders(requestId, collection2) {
|
|
|
25557
25575
|
}
|
|
25558
25576
|
function buildRunPlan(collection2, folderId, filterTags) {
|
|
25559
25577
|
const collectionVars = collection2.collectionVariables ?? {};
|
|
25578
|
+
const tag = (items) => items.map((i) => ({ ...i, collection: collection2.name }));
|
|
25560
25579
|
if (!folderId) {
|
|
25561
|
-
return buildFolderPlan(
|
|
25580
|
+
return tag(buildFolderPlan(
|
|
25562
25581
|
collection2.rootFolder,
|
|
25563
25582
|
collection2.requests,
|
|
25564
25583
|
collectionVars,
|
|
@@ -25568,7 +25587,7 @@ function buildRunPlan(collection2, folderId, filterTags) {
|
|
|
25568
25587
|
[],
|
|
25569
25588
|
[],
|
|
25570
25589
|
true
|
|
25571
|
-
);
|
|
25590
|
+
));
|
|
25572
25591
|
}
|
|
25573
25592
|
const chain = folderChainTo(collection2.rootFolder, folderId);
|
|
25574
25593
|
if (chain.length === 0) return [];
|
|
@@ -25615,7 +25634,7 @@ function buildRunPlan(collection2, folderId, filterTags) {
|
|
|
25615
25634
|
result.push(makeHook(req, collectionVars, "afterAll", f.id, myAncestors, []));
|
|
25616
25635
|
}
|
|
25617
25636
|
}
|
|
25618
|
-
return result;
|
|
25637
|
+
return tag(result);
|
|
25619
25638
|
}
|
|
25620
25639
|
function expandRunPlanWithData(items, ds) {
|
|
25621
25640
|
if (!ds || ds.rows.length === 0) return items;
|
|
@@ -25641,7 +25660,7 @@ function parseDataRow(columns, row) {
|
|
|
25641
25660
|
const key = col.toLowerCase();
|
|
25642
25661
|
const val = row[ci] ?? "";
|
|
25643
25662
|
if (RESERVED_STATUS.has(key)) {
|
|
25644
|
-
const nums = val.split(/[\s,|]+/).map((x) => parseInt(x, 10)).filter((n) => Number.isFinite(n));
|
|
25663
|
+
const nums = val.split(/[\s,|]+/).map((x) => Number.parseInt(x, 10)).filter((n) => Number.isFinite(n));
|
|
25645
25664
|
if (nums.length) expectStatus = nums;
|
|
25646
25665
|
} else if (RESERVED_OWASP.has(key)) {
|
|
25647
25666
|
if (val.trim()) owaspTag = val.trim().toUpperCase();
|
|
@@ -25726,7 +25745,7 @@ async function pushRequestAsMonitor(request2, opts) {
|
|
|
25726
25745
|
const s = useStore.getState();
|
|
25727
25746
|
const colEntry = Object.values(s.collections).find((c) => c.data.requests[request2.id]);
|
|
25728
25747
|
const collectionVars = {
|
|
25729
|
-
...colEntry?.data.collectionVariables
|
|
25748
|
+
...colEntry?.data.collectionVariables,
|
|
25730
25749
|
...s.getInheritedVariables(request2.id),
|
|
25731
25750
|
...s.sessionVars
|
|
25732
25751
|
};
|
|
@@ -25948,12 +25967,13 @@ function InlineEdit({
|
|
|
25948
25967
|
}
|
|
25949
25968
|
onCommit(trimmed);
|
|
25950
25969
|
}
|
|
25951
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", {
|
|
25970
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
25952
25971
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
25953
25972
|
"input",
|
|
25954
25973
|
{
|
|
25955
25974
|
ref,
|
|
25956
25975
|
value: draft,
|
|
25976
|
+
onClick: (e) => e.stopPropagation(),
|
|
25957
25977
|
onChange: (e) => {
|
|
25958
25978
|
setDraft(e.target.value);
|
|
25959
25979
|
setError(null);
|
|
@@ -26045,6 +26065,8 @@ function ContextMenu({ items, x, y, onClose }) {
|
|
|
26045
26065
|
"div",
|
|
26046
26066
|
{
|
|
26047
26067
|
ref,
|
|
26068
|
+
role: "menu",
|
|
26069
|
+
tabIndex: -1,
|
|
26048
26070
|
style: { position: "fixed", top: pos.top, left: pos.left, zIndex: 9999 },
|
|
26049
26071
|
className: "bg-surface-900 border border-surface-700 rounded-lg shadow-2xl py-1 min-w-[170px]",
|
|
26050
26072
|
onMouseDown: (e) => e.stopPropagation(),
|
|
@@ -26095,6 +26117,14 @@ function DotsBtn({ items }) {
|
|
|
26095
26117
|
menu && /* @__PURE__ */ jsxRuntimeExports.jsx(ContextMenu, { items, x: menu.x, y: menu.y, onClose: () => setMenu(null) })
|
|
26096
26118
|
] });
|
|
26097
26119
|
}
|
|
26120
|
+
function onActivateKey(handler) {
|
|
26121
|
+
return (e) => {
|
|
26122
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
26123
|
+
e.preventDefault();
|
|
26124
|
+
handler();
|
|
26125
|
+
}
|
|
26126
|
+
};
|
|
26127
|
+
}
|
|
26098
26128
|
function useToast(durationMs = 3e3) {
|
|
26099
26129
|
const [toast, setToast] = reactExports.useState(null);
|
|
26100
26130
|
const timer = reactExports.useRef(null);
|
|
@@ -26201,6 +26231,14 @@ function RequestRow({
|
|
|
26201
26231
|
"div",
|
|
26202
26232
|
{
|
|
26203
26233
|
draggable: true,
|
|
26234
|
+
role: "button",
|
|
26235
|
+
tabIndex: 0,
|
|
26236
|
+
onKeyDown: (e) => {
|
|
26237
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
26238
|
+
e.preventDefault();
|
|
26239
|
+
handleRowClick(e);
|
|
26240
|
+
}
|
|
26241
|
+
},
|
|
26204
26242
|
className: `group flex items-start gap-1.5 py-1 pr-1 rounded-sm cursor-pointer transition-colors ${disabled ? "opacity-40" : ""} ${selected ? "bg-blue-950/40 ring-1 ring-inset ring-blue-500" : isActive ? "bg-surface-800 text-[var(--text-primary)]" : "text-surface-300 hover:bg-surface-800"}`,
|
|
26205
26243
|
style: { paddingLeft: indent },
|
|
26206
26244
|
onClick: handleRowClick,
|
|
@@ -26350,7 +26388,10 @@ function ExampleRow({ name, indent, isActive, onOpen, onRename, onDelete, onDupl
|
|
|
26350
26388
|
{
|
|
26351
26389
|
className: `group flex items-center gap-1.5 py-1 pr-1 rounded-sm cursor-pointer transition-colors ${isActive ? "bg-surface-800 text-[var(--text-primary)]" : "text-surface-400 hover:bg-surface-800"}`,
|
|
26352
26390
|
style: { paddingLeft: indent },
|
|
26391
|
+
role: "button",
|
|
26392
|
+
tabIndex: 0,
|
|
26353
26393
|
onClick: onOpen,
|
|
26394
|
+
onKeyDown: onActivateKey(onOpen),
|
|
26354
26395
|
onDoubleClick: () => setRenaming(true),
|
|
26355
26396
|
children: [
|
|
26356
26397
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 text-[8px] font-bold px-1 py-px rounded bg-surface-700 text-surface-300", title: t("Example"), children: "EX" }),
|
|
@@ -26466,46 +26507,56 @@ function TagChips({
|
|
|
26466
26507
|
setAdding(false);
|
|
26467
26508
|
onDoneAdding?.();
|
|
26468
26509
|
}
|
|
26469
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
26470
|
-
|
|
26471
|
-
|
|
26472
|
-
|
|
26473
|
-
|
|
26474
|
-
|
|
26475
|
-
|
|
26476
|
-
|
|
26477
|
-
|
|
26478
|
-
|
|
26479
|
-
|
|
26480
|
-
|
|
26481
|
-
|
|
26482
|
-
|
|
26483
|
-
|
|
26484
|
-
|
|
26485
|
-
|
|
26486
|
-
|
|
26487
|
-
|
|
26488
|
-
|
|
26489
|
-
|
|
26490
|
-
|
|
26491
|
-
|
|
26492
|
-
|
|
26493
|
-
|
|
26494
|
-
|
|
26495
|
-
|
|
26496
|
-
|
|
26497
|
-
|
|
26498
|
-
|
|
26499
|
-
|
|
26510
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
26511
|
+
"div",
|
|
26512
|
+
{
|
|
26513
|
+
role: "group",
|
|
26514
|
+
"aria-label": "Tags",
|
|
26515
|
+
className: "flex flex-wrap items-center gap-0.5 mt-0.5",
|
|
26516
|
+
onClick: (e) => e.stopPropagation(),
|
|
26517
|
+
onKeyDown: (e) => e.stopPropagation(),
|
|
26518
|
+
children: [
|
|
26519
|
+
tags.map((tag) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
26520
|
+
"span",
|
|
26521
|
+
{
|
|
26522
|
+
className: "flex items-center gap-0.5 px-1 py-px rounded text-[9px] bg-blue-900/50 text-blue-300 border border-blue-800/50",
|
|
26523
|
+
children: [
|
|
26524
|
+
tag,
|
|
26525
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
26526
|
+
"button",
|
|
26527
|
+
{
|
|
26528
|
+
onClick: () => onRemove(tag),
|
|
26529
|
+
className: "hover:text-red-400 leading-none ml-0.5",
|
|
26530
|
+
children: "×"
|
|
26531
|
+
}
|
|
26532
|
+
)
|
|
26533
|
+
]
|
|
26534
|
+
},
|
|
26535
|
+
tag
|
|
26536
|
+
)),
|
|
26537
|
+
adding ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
26538
|
+
"input",
|
|
26539
|
+
{
|
|
26540
|
+
ref: inputRef,
|
|
26541
|
+
value: draft,
|
|
26542
|
+
onChange: (e) => setDraft(e.target.value),
|
|
26543
|
+
onKeyDown: (e) => {
|
|
26544
|
+
if (e.key === "Enter") commit();
|
|
26545
|
+
if (e.key === "Escape") {
|
|
26546
|
+
setAdding(false);
|
|
26547
|
+
setDraft("");
|
|
26548
|
+
onDoneAdding?.();
|
|
26549
|
+
}
|
|
26550
|
+
e.stopPropagation();
|
|
26551
|
+
},
|
|
26552
|
+
onBlur: commit,
|
|
26553
|
+
className: "w-16 text-[9px] bg-surface-700 rounded px-1 py-px focus:outline-none focus:ring-1 focus:ring-blue-500",
|
|
26554
|
+
placeholder: t("tag…")
|
|
26500
26555
|
}
|
|
26501
|
-
|
|
26502
|
-
|
|
26503
|
-
|
|
26504
|
-
|
|
26505
|
-
placeholder: t("tag…")
|
|
26506
|
-
}
|
|
26507
|
-
) : null
|
|
26508
|
-
] });
|
|
26556
|
+
) : null
|
|
26557
|
+
]
|
|
26558
|
+
}
|
|
26559
|
+
);
|
|
26509
26560
|
}
|
|
26510
26561
|
function methodColor$2(method) {
|
|
26511
26562
|
switch (method) {
|
|
@@ -26602,12 +26653,12 @@ function CollectionTree() {
|
|
|
26602
26653
|
} });
|
|
26603
26654
|
}
|
|
26604
26655
|
function onDropRequest(destCollectionId, destFolderId, destIndex) {
|
|
26605
|
-
if (
|
|
26656
|
+
if (dragging?.type !== "request") return;
|
|
26606
26657
|
moveRequest(dragging.collectionId, dragging.requestId, destCollectionId, destFolderId, destIndex);
|
|
26607
26658
|
setDragging(null);
|
|
26608
26659
|
}
|
|
26609
26660
|
function onDropFolder(destCollectionId, destParentFolderId, destIndex) {
|
|
26610
|
-
if (
|
|
26661
|
+
if (dragging?.type !== "folder") return;
|
|
26611
26662
|
if (dragging.collectionId !== destCollectionId) return;
|
|
26612
26663
|
moveFolder(dragging.collectionId, dragging.folderId, destParentFolderId, destIndex);
|
|
26613
26664
|
setDragging(null);
|
|
@@ -26830,10 +26881,16 @@ function CollectionNode({
|
|
|
26830
26881
|
"div",
|
|
26831
26882
|
{
|
|
26832
26883
|
className: `group flex items-center gap-1 px-2 py-1.5 cursor-pointer hover:bg-surface-800 transition-colors ${panelActive ? "bg-surface-800 text-[var(--text-primary)]" : isActive ? "text-[var(--text-primary)]" : "text-surface-400"} ${col.disabled ? "opacity-50" : ""} ${dropOver ? "outline outline-1 outline-blue-500 rounded" : ""}`,
|
|
26884
|
+
role: "button",
|
|
26885
|
+
tabIndex: 0,
|
|
26833
26886
|
onClick: () => {
|
|
26834
26887
|
onSelectCollection();
|
|
26835
26888
|
setExpanded((e) => !e);
|
|
26836
26889
|
},
|
|
26890
|
+
onKeyDown: onActivateKey(() => {
|
|
26891
|
+
onSelectCollection();
|
|
26892
|
+
setExpanded((e) => !e);
|
|
26893
|
+
}),
|
|
26837
26894
|
onDragOver: dragCtx.dragging ? (e) => {
|
|
26838
26895
|
e.preventDefault();
|
|
26839
26896
|
setDropOver(true);
|
|
@@ -26989,10 +27046,16 @@ function FolderRow({
|
|
|
26989
27046
|
draggable: true,
|
|
26990
27047
|
className: `group flex items-center gap-1 py-1 transition-colors cursor-pointer ${isActive ? "bg-surface-800 text-[var(--text-primary)]" : "text-surface-400 hover:bg-surface-800"} ${folder2.disabled ? "opacity-40" : ""} ${dropInside ? "outline outline-1 outline-blue-500 rounded" : ""}`,
|
|
26991
27048
|
style: { paddingLeft: indent },
|
|
27049
|
+
role: "button",
|
|
27050
|
+
tabIndex: 0,
|
|
26992
27051
|
onClick: () => {
|
|
26993
27052
|
openFolderPanel(collectionId, folder2.id);
|
|
26994
27053
|
setExpanded((e) => !e);
|
|
26995
27054
|
},
|
|
27055
|
+
onKeyDown: onActivateKey(() => {
|
|
27056
|
+
openFolderPanel(collectionId, folder2.id);
|
|
27057
|
+
setExpanded((e) => !e);
|
|
27058
|
+
}),
|
|
26996
27059
|
onDragStart: (e) => {
|
|
26997
27060
|
e.dataTransfer.effectAllowed = "move";
|
|
26998
27061
|
e.stopPropagation();
|
|
@@ -27375,8 +27438,8 @@ function jsonWithComments() {
|
|
|
27375
27438
|
function xmlWithComments() {
|
|
27376
27439
|
return [xml(), commentKeymap];
|
|
27377
27440
|
}
|
|
27378
|
-
const GraphQLEditor = reactExports.lazy(() => __vitePreload(() => import("./GraphQLEditor-
|
|
27379
|
-
const SoapEditor = reactExports.lazy(() => __vitePreload(() => import("./SoapEditor-
|
|
27441
|
+
const GraphQLEditor = reactExports.lazy(() => __vitePreload(() => import("./GraphQLEditor-Bih8eb_r.js"), true ? __vite__mapDeps([0,1,2]) : void 0, import.meta.url).then((m) => ({ default: m.GraphQLEditor })));
|
|
27442
|
+
const SoapEditor = reactExports.lazy(() => __vitePreload(() => import("./SoapEditor-D1sQKu7l.js"), true ? __vite__mapDeps([3,1,2]) : void 0, import.meta.url).then((m) => ({ default: m.SoapEditor })));
|
|
27380
27443
|
function BodyTab({ request: request2, onChange }) {
|
|
27381
27444
|
const t = useT();
|
|
27382
27445
|
const editorFallback = /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 text-xs text-surface-500", children: t("Loading editor…") });
|
|
@@ -27608,7 +27671,7 @@ function AuthTab({ request: request2, onChange }) {
|
|
|
27608
27671
|
{
|
|
27609
27672
|
type: "number",
|
|
27610
27673
|
value: auth.oauth2RedirectPort ?? 9876,
|
|
27611
|
-
onChange: (e) => setAuth({ oauth2RedirectPort: parseInt(e.target.value, 10) || 9876 }),
|
|
27674
|
+
onChange: (e) => setAuth({ oauth2RedirectPort: Number.parseInt(e.target.value, 10) || 9876 }),
|
|
27612
27675
|
className: "mt-1 w-full bg-surface-800 border border-surface-700 rounded px-2 py-1 focus:outline-none focus:border-blue-500"
|
|
27613
27676
|
}
|
|
27614
27677
|
)
|
|
@@ -28231,17 +28294,17 @@ function renderInline(text, keyBase) {
|
|
|
28231
28294
|
});
|
|
28232
28295
|
}
|
|
28233
28296
|
function renderMarkdown(md) {
|
|
28234
|
-
const lines = md.
|
|
28297
|
+
const lines = md.replaceAll("\r\n", "\n").split("\n");
|
|
28235
28298
|
const blocks = [];
|
|
28236
28299
|
let i = 0;
|
|
28237
28300
|
let key = 0;
|
|
28238
28301
|
const k = () => `md-${key++}`;
|
|
28239
28302
|
while (i < lines.length) {
|
|
28240
28303
|
const line = lines[i];
|
|
28241
|
-
if (
|
|
28304
|
+
if (line.trim().startsWith("```")) {
|
|
28242
28305
|
const buf2 = [];
|
|
28243
28306
|
i++;
|
|
28244
|
-
while (i < lines.length &&
|
|
28307
|
+
while (i < lines.length && !lines[i].trim().startsWith("```")) {
|
|
28245
28308
|
buf2.push(lines[i]);
|
|
28246
28309
|
i++;
|
|
28247
28310
|
}
|
|
@@ -28300,7 +28363,7 @@ function renderMarkdown(md) {
|
|
|
28300
28363
|
continue;
|
|
28301
28364
|
}
|
|
28302
28365
|
const buf = [];
|
|
28303
|
-
while (i < lines.length && lines[i].trim() !== "" &&
|
|
28366
|
+
while (i < lines.length && lines[i].trim() !== "" && !lines[i].trim().startsWith("```") && !/^(#{1,6})\s+/.test(lines[i]) && !/^\s*>\s?/.test(lines[i]) && !/^\s*[-*+]\s+/.test(lines[i]) && !/^\s*\d+\.\s+/.test(lines[i]) && !/^\s*([-*_])\1{2,}\s*$/.test(lines[i])) {
|
|
28304
28367
|
buf.push(lines[i]);
|
|
28305
28368
|
i++;
|
|
28306
28369
|
}
|
|
@@ -28452,7 +28515,7 @@ function useAiAvailable() {
|
|
|
28452
28515
|
return available;
|
|
28453
28516
|
}
|
|
28454
28517
|
async function generateDocs(input) {
|
|
28455
|
-
return electron$u.
|
|
28518
|
+
return electron$u.generateAiDocs({ ...input, model: getAiConfig().model });
|
|
28456
28519
|
}
|
|
28457
28520
|
function kvLines(label, rows) {
|
|
28458
28521
|
const on = (rows ?? []).filter((r) => r.enabled !== false && r.key);
|
|
@@ -28465,8 +28528,7 @@ function requestDocsContext(req, example) {
|
|
|
28465
28528
|
`Method: ${req.method}`,
|
|
28466
28529
|
`URL: ${req.url}`
|
|
28467
28530
|
];
|
|
28468
|
-
lines.push(...kvLines("Query params", req.params));
|
|
28469
|
-
lines.push(...kvLines("Headers", req.headers));
|
|
28531
|
+
lines.push(...kvLines("Query params", req.params), ...kvLines("Headers", req.headers));
|
|
28470
28532
|
if (req.auth && req.auth.type !== "none") lines.push(`Auth: ${req.auth.type}`);
|
|
28471
28533
|
if (req.body && req.body.mode !== "none") {
|
|
28472
28534
|
lines.push(`Request body (${req.body.mode}):`);
|
|
@@ -28474,8 +28536,7 @@ function requestDocsContext(req, example) {
|
|
|
28474
28536
|
if (raw) lines.push(raw.slice(0, 2e3));
|
|
28475
28537
|
}
|
|
28476
28538
|
if (example?.response) {
|
|
28477
|
-
lines.push(`Example response (status ${example.response.status})
|
|
28478
|
-
lines.push((example.response.body || "").slice(0, 2e3));
|
|
28539
|
+
lines.push(`Example response (status ${example.response.status}):`, (example.response.body || "").slice(0, 2e3));
|
|
28479
28540
|
}
|
|
28480
28541
|
return lines.join("\n");
|
|
28481
28542
|
}
|
|
@@ -28496,8 +28557,7 @@ function collectionDocsContext(col) {
|
|
|
28496
28557
|
const lines = [`API collection with ${reqs.length} request(s).`];
|
|
28497
28558
|
const byMethod = {};
|
|
28498
28559
|
for (const r of reqs) byMethod[r.method] = (byMethod[r.method] ?? 0) + 1;
|
|
28499
|
-
lines.push("Methods: " + Object.entries(byMethod).map(([m, n]) => `${m}×${n}`).join(", "));
|
|
28500
|
-
lines.push("Endpoints:");
|
|
28560
|
+
lines.push("Methods: " + Object.entries(byMethod).map(([m, n]) => `${m}×${n}`).join(", "), "Endpoints:");
|
|
28501
28561
|
for (const r of reqs.slice(0, 60)) lines.push(` - ${r.method} ${r.url}`);
|
|
28502
28562
|
if (reqs.length > 60) lines.push(` … and ${reqs.length - 60} more`);
|
|
28503
28563
|
return lines.join("\n");
|
|
@@ -28764,7 +28824,7 @@ function textToMeta(text) {
|
|
|
28764
28824
|
}
|
|
28765
28825
|
function GrpcPanel({ request: request2, onChange }) {
|
|
28766
28826
|
const t = useT();
|
|
28767
|
-
const grpc = { ...DEFAULT_GRPC, ...request2.body.grpc
|
|
28827
|
+
const grpc = { ...DEFAULT_GRPC, ...request2.body.grpc };
|
|
28768
28828
|
const grpcCalls = useStore((s) => s.grpcCalls);
|
|
28769
28829
|
const setGrpcStatus = useStore((s) => s.setGrpcStatus);
|
|
28770
28830
|
const addGrpcMessage = useStore((s) => s.addGrpcMessage);
|
|
@@ -29924,7 +29984,7 @@ function XmlNode({ element, depth, onLeaf }) {
|
|
|
29924
29984
|
] });
|
|
29925
29985
|
}
|
|
29926
29986
|
function esc(s) {
|
|
29927
|
-
return s.
|
|
29987
|
+
return s.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("\n", "\\n").replaceAll(/\r/g, "");
|
|
29928
29988
|
}
|
|
29929
29989
|
function toLit(v) {
|
|
29930
29990
|
if (v === null) return "null";
|
|
@@ -29961,7 +30021,7 @@ function toJsonPathExpr(path, filterKey, filterValue) {
|
|
|
29961
30021
|
const prefix2 = path.slice(0, arrayIdx).join(".");
|
|
29962
30022
|
const arrayPart = prefix2 ? "$." + prefix2 : "$";
|
|
29963
30023
|
const leafPart = path.slice(arrayIdx + 1).join(".");
|
|
29964
|
-
const filterVal = isNaN(Number(filterValue)) ? `"${filterValue.
|
|
30024
|
+
const filterVal = Number.isNaN(Number(filterValue)) ? `"${filterValue.replaceAll('"', '\\"')}"` : filterValue;
|
|
29965
30025
|
return leafPart ? `${arrayPart}[?(@.${filterKey}==${filterVal})].${leafPart}` : `${arrayPart}[?(@.${filterKey}==${filterVal})]`;
|
|
29966
30026
|
}
|
|
29967
30027
|
function varNameFromPath(path) {
|
|
@@ -30003,7 +30063,7 @@ function makeJsonPathSnippet(path, value2, filterKey, filterValue) {
|
|
|
30003
30063
|
});`;
|
|
30004
30064
|
}
|
|
30005
30065
|
function makeXmlSnippet(selector, value2, mode) {
|
|
30006
|
-
const sel = selector.
|
|
30066
|
+
const sel = selector.replaceAll('"', '\\"');
|
|
30007
30067
|
switch (mode) {
|
|
30008
30068
|
case "equals":
|
|
30009
30069
|
return `sp.test('${selector} equals "${esc(value2)}"', function() {
|
|
@@ -30031,7 +30091,7 @@ function makeJsonPathExtractSnippet(path, filterKey, filterValue, target) {
|
|
|
30031
30091
|
sp.${target}.set("${varName}", String(matches[0] ?? ''));`;
|
|
30032
30092
|
}
|
|
30033
30093
|
function makeXmlExtractSnippet(selector, target) {
|
|
30034
|
-
return `sp.${target}.set("extracted_value", sp.response.xmlText("${selector.
|
|
30094
|
+
return `sp.${target}.set("extracted_value", sp.response.xmlText("${selector.replaceAll('"', '\\"')}") ?? '');`;
|
|
30035
30095
|
}
|
|
30036
30096
|
function AssertMenu({ state, onClose, onConfirm }) {
|
|
30037
30097
|
const t = useT();
|
|
@@ -30330,7 +30390,7 @@ function findPrimaryArray(data) {
|
|
|
30330
30390
|
const { node, path, depth } = queue.shift();
|
|
30331
30391
|
if (depth > 6 || node === null || typeof node !== "object") continue;
|
|
30332
30392
|
if (Array.isArray(node)) {
|
|
30333
|
-
const key = (path.split(".").pop() ?? "").
|
|
30393
|
+
const key = (path.split(".").pop() ?? "").replaceAll(/\[\d+\]/g, "");
|
|
30334
30394
|
const objs = node.filter((x) => x && typeof x === "object" && !Array.isArray(x)).length;
|
|
30335
30395
|
found.push({ path, array: node, pref: PREFERRED.test(key) ? 1 : 0, objs, depth });
|
|
30336
30396
|
} else {
|
|
@@ -30714,7 +30774,7 @@ function HookResultsPanel({ results }) {
|
|
|
30714
30774
|
"div",
|
|
30715
30775
|
{
|
|
30716
30776
|
className: `flex items-center gap-2 py-0.5 ${hasDetail2 ? "cursor-pointer hover:bg-surface-800/20 rounded px-1 -mx-1" : ""}`,
|
|
30717
|
-
onClick: () =>
|
|
30777
|
+
...hasDetail2 ? { role: "button", tabIndex: 0, onClick: () => toggle(r.requestId + i), onKeyDown: onActivateKey(() => toggle(r.requestId + i)) } : {},
|
|
30718
30778
|
children: [
|
|
30719
30779
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `w-1.5 h-1.5 rounded-full shrink-0 ${r.status === "passed" ? "bg-emerald-500" : r.status === "failed" ? "bg-red-500" : "bg-orange-500"}` }),
|
|
30720
30780
|
badge && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[9px] font-bold px-1 py-0.5 rounded uppercase tracking-wide shrink-0 ${badge.cls}`, children: t(badge.label) }),
|
|
@@ -30750,7 +30810,7 @@ function extractPath(url) {
|
|
|
30750
30810
|
try {
|
|
30751
30811
|
return new URL(url).pathname || "/";
|
|
30752
30812
|
} catch {
|
|
30753
|
-
const match =
|
|
30813
|
+
const match = /(?:https?:\/\/[^/]+)?(\/[^?]*)/.exec(url);
|
|
30754
30814
|
return match?.[1] ?? "/";
|
|
30755
30815
|
}
|
|
30756
30816
|
}
|
|
@@ -31220,6 +31280,7 @@ function OverflowMenu({ button, ariaLabel, title, wrapperClassName = "", buttonC
|
|
|
31220
31280
|
ref: menuRef,
|
|
31221
31281
|
id: menuId,
|
|
31222
31282
|
role: "menu",
|
|
31283
|
+
tabIndex: -1,
|
|
31223
31284
|
"aria-label": ariaLabel,
|
|
31224
31285
|
onKeyDown: onMenuKeyDown,
|
|
31225
31286
|
onClick: () => setOpen(false),
|
|
@@ -31253,7 +31314,7 @@ function validateHttpSemantics(res, opts = {}) {
|
|
|
31253
31314
|
const body = hasBody(res);
|
|
31254
31315
|
const contentType = header(res.headers, "content-type");
|
|
31255
31316
|
const contentEncoding = header(res.headers, "content-encoding");
|
|
31256
|
-
const clNum = Number(header(res.headers, "content-length") ?? NaN);
|
|
31317
|
+
const clNum = Number(header(res.headers, "content-length") ?? Number.NaN);
|
|
31257
31318
|
const isBodiless = status in BODILESS || status >= 100 && status < 200;
|
|
31258
31319
|
if (isBodiless) {
|
|
31259
31320
|
const declaresBody = body || Number.isFinite(clNum) && clNum > 0;
|
|
@@ -31442,7 +31503,7 @@ function ResponseViewer() {
|
|
|
31442
31503
|
const setTabScriptTab = useStore((s) => s.setTabScriptTab);
|
|
31443
31504
|
const isSending = activeTab?.isSending ?? false;
|
|
31444
31505
|
const liveStream = useStore((s) => s.liveStream);
|
|
31445
|
-
const streamForTab = liveStream
|
|
31506
|
+
const streamForTab = liveStream?.tabId === activeTabId ? liveStream : null;
|
|
31446
31507
|
const response = activeTab?.lastResponse ?? null;
|
|
31447
31508
|
const scriptResult = activeTab?.lastScriptResult ?? null;
|
|
31448
31509
|
const sentRequest = activeTab?.lastSentRequest ?? null;
|
|
@@ -31669,7 +31730,7 @@ function ResponseViewer() {
|
|
|
31669
31730
|
" KB"
|
|
31670
31731
|
] })
|
|
31671
31732
|
] }),
|
|
31672
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { role: "tablist", "aria-label": t("Response sections"), onKeyDown: onTablistKey, className: "flex items-center gap-0 min-w-0 ml-1", children: [
|
|
31733
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { role: "tablist", tabIndex: -1, "aria-label": t("Response sections"), onKeyDown: onTablistKey, className: "flex items-center gap-0 min-w-0 ml-1", children: [
|
|
31673
31734
|
tabList.map((def) => renderTabButton(def, "inline")),
|
|
31674
31735
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31675
31736
|
OverflowMenu,
|
|
@@ -31923,7 +31984,7 @@ function ResponseViewer() {
|
|
|
31923
31984
|
type: "item",
|
|
31924
31985
|
label: t('Create variable in ":env"', { env: activeEnvName ?? "" }),
|
|
31925
31986
|
onClick: () => {
|
|
31926
|
-
setVarDialog({ name: headerMenu.key.
|
|
31987
|
+
setVarDialog({ name: headerMenu.key.replaceAll(/[^a-zA-Z0-9]+/g, "_").replaceAll(/^_+|_+$/g, ""), value: headerMenu.value });
|
|
31927
31988
|
setHeaderMenu(null);
|
|
31928
31989
|
}
|
|
31929
31990
|
} : { type: "header", label: t("Select an environment first") }
|
|
@@ -32332,7 +32393,7 @@ function HistoryPanel() {
|
|
|
32332
32393
|
return out;
|
|
32333
32394
|
}, [history, search]);
|
|
32334
32395
|
async function downloadHar() {
|
|
32335
|
-
const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).
|
|
32396
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replaceAll(/[:T]/g, "-");
|
|
32336
32397
|
await electron$l.saveResults(historyToHar(history), `api-spector-history-${stamp}.har`);
|
|
32337
32398
|
}
|
|
32338
32399
|
function open2(entry) {
|
|
@@ -32536,7 +32597,7 @@ function WelcomeScreen() {
|
|
|
32536
32597
|
)
|
|
32537
32598
|
] }),
|
|
32538
32599
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-surface-400 text-sm max-w-sm", children: t("Local-first API testing with Robot Framework & Playwright code generation. Secrets stay on your machine.") }),
|
|
32539
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] mt-3", style: { color: "var(--text-muted)" }, children: t("version :version", { version: "0.6.
|
|
32600
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] mt-3", style: { color: "var(--text-muted)" }, children: t("version :version", { version: "0.6.4" }) })
|
|
32540
32601
|
] }),
|
|
32541
32602
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3 w-64", children: [
|
|
32542
32603
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -32806,8 +32867,7 @@ function EnvironmentEditor({ onClose }) {
|
|
|
32806
32867
|
}
|
|
32807
32868
|
function handleDelete(id) {
|
|
32808
32869
|
deleteEnvironment(id);
|
|
32809
|
-
|
|
32810
|
-
setSelectedId(remaining[0] ?? "");
|
|
32870
|
+
setSelectedId(Object.keys(environments).find((k) => k !== id) ?? "");
|
|
32811
32871
|
}
|
|
32812
32872
|
function handleDuplicate(id) {
|
|
32813
32873
|
duplicateEnvironment(id);
|
|
@@ -33259,7 +33319,7 @@ function EnvironmentBar({ inline = false }) {
|
|
|
33259
33319
|
style: { color: "var(--text-primary)" },
|
|
33260
33320
|
children: [
|
|
33261
33321
|
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: t("No env") }),
|
|
33262
|
-
envList.map(({ data: env2 }) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: env2.id, children:
|
|
33322
|
+
envList.map(({ data: env2 }) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: env2.id, children: env2.name.toLowerCase() === defaultEnvName?.toLowerCase() ? t(":name (default)", { name: env2.name }) : env2.name }, env2.id))
|
|
33263
33323
|
]
|
|
33264
33324
|
}
|
|
33265
33325
|
),
|
|
@@ -33541,7 +33601,7 @@ function WorkspaceSettingsModal({ onClose }) {
|
|
|
33541
33601
|
}
|
|
33542
33602
|
async function save() {
|
|
33543
33603
|
const settings = {
|
|
33544
|
-
...workspace?.settings
|
|
33604
|
+
...workspace?.settings
|
|
33545
33605
|
};
|
|
33546
33606
|
if (proxyUrl.trim()) {
|
|
33547
33607
|
settings.proxy = { url: proxyUrl.trim() };
|
|
@@ -33660,6 +33720,7 @@ function WorkspaceSettingsModal({ onClose }) {
|
|
|
33660
33720
|
"input",
|
|
33661
33721
|
{
|
|
33662
33722
|
type: "checkbox",
|
|
33723
|
+
"aria-label": t("Persist request history"),
|
|
33663
33724
|
checked: persistHistory,
|
|
33664
33725
|
onChange: (e) => setPersistHistory(e.target.checked),
|
|
33665
33726
|
className: "mt-0.5"
|
|
@@ -33795,6 +33856,7 @@ function WorkspaceSettingsModal({ onClose }) {
|
|
|
33795
33856
|
"input",
|
|
33796
33857
|
{
|
|
33797
33858
|
type: "checkbox",
|
|
33859
|
+
"aria-label": t("Enable API Spector Cloud"),
|
|
33798
33860
|
checked: cloudEnabled2,
|
|
33799
33861
|
onChange: (e) => setCloudEnabled(e.target.checked),
|
|
33800
33862
|
className: "mt-0.5 accent-blue-500"
|
|
@@ -34572,12 +34634,12 @@ function parseCurl(command) {
|
|
|
34572
34634
|
} else if (hasData) {
|
|
34573
34635
|
const data = dataParts.join("&");
|
|
34574
34636
|
const ct = headers.find((h) => h.key.toLowerCase() === "content-type")?.value;
|
|
34575
|
-
if (ct
|
|
34637
|
+
if (ct?.includes("json") || looksJson(data)) body = { mode: "json", json: data };
|
|
34576
34638
|
else body = { mode: "raw", raw: data, rawContentType: ct ?? "application/x-www-form-urlencoded" };
|
|
34577
34639
|
}
|
|
34578
34640
|
let name;
|
|
34579
34641
|
try {
|
|
34580
|
-
const u = new URL(url.
|
|
34642
|
+
const u = new URL(url.replaceAll(/\{\{[^}]+\}\}/g, "x"));
|
|
34581
34643
|
name = `${resolvedMethod} ${u.pathname === "/" ? u.hostname : u.pathname}`;
|
|
34582
34644
|
} catch {
|
|
34583
34645
|
const cleaned = url.replace(/^[a-z]+:\/\//i, "").replace(/\?.*$/, "");
|
|
@@ -35426,7 +35488,7 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
35426
35488
|
] });
|
|
35427
35489
|
}
|
|
35428
35490
|
function escapeHtml(s) {
|
|
35429
|
-
return String(s ?? "").
|
|
35491
|
+
return String(s ?? "").replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
35430
35492
|
}
|
|
35431
35493
|
function buildJsonReport(results, summary, meta = {}) {
|
|
35432
35494
|
return JSON.stringify({
|
|
@@ -35440,6 +35502,9 @@ function buildJsonReport(results, summary, meta = {}) {
|
|
|
35440
35502
|
method: r.method,
|
|
35441
35503
|
url: r.resolvedUrl,
|
|
35442
35504
|
status: r.status,
|
|
35505
|
+
// Tree position: which collection and folder path this request sits under.
|
|
35506
|
+
collection: r.collection ?? meta.collection ?? null,
|
|
35507
|
+
folderPath: r.scopePath ?? [],
|
|
35443
35508
|
isHook: r.isHook ?? false,
|
|
35444
35509
|
hookType: r.hookType ?? null,
|
|
35445
35510
|
httpStatus: r.httpStatus ?? null,
|
|
@@ -35480,12 +35545,26 @@ function buildHtmlReport(results, summary, meta = {}) {
|
|
|
35480
35545
|
after: "AFTER",
|
|
35481
35546
|
afterAll: "AFTER ALL"
|
|
35482
35547
|
};
|
|
35483
|
-
let
|
|
35548
|
+
let lastCollection = null;
|
|
35549
|
+
let lastPath = [];
|
|
35484
35550
|
const cards = results.map((r, idx) => {
|
|
35485
|
-
|
|
35486
|
-
const
|
|
35487
|
-
|
|
35488
|
-
|
|
35551
|
+
let groupHeading = "";
|
|
35552
|
+
const coll = r.collection ?? meta.collection ?? "";
|
|
35553
|
+
if (coll && coll !== lastCollection) {
|
|
35554
|
+
groupHeading += ` <div class="scope-heading lvl-0">${esc2(coll)}</div>
|
|
35555
|
+
`;
|
|
35556
|
+
lastCollection = coll;
|
|
35557
|
+
lastPath = [];
|
|
35558
|
+
}
|
|
35559
|
+
const path = r.scopePath ?? [];
|
|
35560
|
+
let diverge = 0;
|
|
35561
|
+
while (diverge < path.length && diverge < lastPath.length && path[diverge] === lastPath[diverge]) diverge++;
|
|
35562
|
+
for (let d = diverge; d < path.length; d++) {
|
|
35563
|
+
groupHeading += ` <div class="scope-heading lvl-${Math.min(d + 1, 6)}">${esc2(path[d])}</div>
|
|
35564
|
+
`;
|
|
35565
|
+
}
|
|
35566
|
+
lastPath = path;
|
|
35567
|
+
const cardIndent = `lvl-${Math.min(path.length + 1, 6)}`;
|
|
35489
35568
|
const statusCls = r.status === "passed" ? "badge-pass" : r.status === "failed" ? "badge-fail" : r.status === "skipped" ? "badge-skip" : "badge-err";
|
|
35490
35569
|
const httpCls = r.httpStatus && r.httpStatus < 300 ? "http-ok" : r.httpStatus && r.httpStatus < 400 ? "http-redir" : "http-err";
|
|
35491
35570
|
const dur = r.durationMs != null ? `${r.durationMs} ms` : "—";
|
|
@@ -35525,7 +35604,7 @@ function buildHtmlReport(results, summary, meta = {}) {
|
|
|
35525
35604
|
</div>` : "";
|
|
35526
35605
|
const hookCls = hookLabel ? r.hookType?.startsWith("before") ? "card-hook-before" : "card-hook-after" : "";
|
|
35527
35606
|
return `${groupHeading}
|
|
35528
|
-
<div class="card ${hookCls}" id="r${idx}">
|
|
35607
|
+
<div class="card ${hookCls} ${cardIndent}" id="r${idx}">
|
|
35529
35608
|
<div class="card-header" onclick="toggle(${idx})">
|
|
35530
35609
|
<span class="chevron" id="ch${idx}">▶</span>
|
|
35531
35610
|
<span class="badge ${statusCls}">${r.status}</span>
|
|
@@ -35596,8 +35675,18 @@ function buildHtmlReport(results, summary, meta = {}) {
|
|
|
35596
35675
|
.stat-skip .stat-val { color: var(--text-muted); }
|
|
35597
35676
|
/* Cards */
|
|
35598
35677
|
.card { border: 1px solid var(--border); border-radius: 8px; margin-bottom: 8px; overflow: hidden; }
|
|
35599
|
-
.scope-heading { margin:
|
|
35678
|
+
.scope-heading { margin: 14px 0 6px; padding: 4px 2px; font-size: 11px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; border-bottom: 1px solid var(--border); }
|
|
35600
35679
|
.scope-heading::before { content: "\\25B8 "; color: var(--text-dim); }
|
|
35680
|
+
/* Nested tree indentation: collection (lvl-0) → folders (lvl-1..) → request card. */
|
|
35681
|
+
.lvl-0 { margin-left: 0; }
|
|
35682
|
+
.lvl-1 { margin-left: 16px; }
|
|
35683
|
+
.lvl-2 { margin-left: 32px; }
|
|
35684
|
+
.lvl-3 { margin-left: 48px; }
|
|
35685
|
+
.lvl-4 { margin-left: 64px; }
|
|
35686
|
+
.lvl-5 { margin-left: 80px; }
|
|
35687
|
+
.lvl-6 { margin-left: 96px; }
|
|
35688
|
+
.scope-heading.lvl-0 { font-size: 13px; color: var(--text); text-transform: none; letter-spacing: 0; margin-top: 22px; }
|
|
35689
|
+
.scope-heading.lvl-0::before { content: "\\1F5C0 "; }
|
|
35601
35690
|
.card-header { display: flex; align-items: baseline; gap: 8px; padding: 10px 14px; cursor: pointer; user-select: none; }
|
|
35602
35691
|
.card-header:hover { background: var(--bg-surface); }
|
|
35603
35692
|
.chevron { font-size: 10px; color: var(--text-muted); min-width: 10px; transition: transform .15s; }
|
|
@@ -35715,7 +35804,7 @@ function buildJUnitReport(results, summary, meta = {}) {
|
|
|
35715
35804
|
const label = r.iterationLabel ? ` #${r.iterationLabel}` : "";
|
|
35716
35805
|
const hookPrefix = r.isHook && r.hookType ? `[${HOOK_JUNIT_LABELS[r.hookType] ?? "Hook"}] ` : "";
|
|
35717
35806
|
const name = esc2(hookPrefix + r.name + label);
|
|
35718
|
-
const classname = esc2(
|
|
35807
|
+
const classname = esc2([r.collection ?? meta.collection, ...r.scopePath ?? []].filter(Boolean).map((s) => String(s).replaceAll(".", "_")).join(".") || "API Tests");
|
|
35719
35808
|
const timeSec = ((r.durationMs ?? 0) / 1e3).toFixed(3);
|
|
35720
35809
|
const failures = [];
|
|
35721
35810
|
if (r.status === "error") {
|
|
@@ -36300,13 +36389,13 @@ function RunnerModal() {
|
|
|
36300
36389
|
}
|
|
36301
36390
|
);
|
|
36302
36391
|
}
|
|
36303
|
-
const HTTP_METHODS$2 = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
36392
|
+
const HTTP_METHODS$2 = /* @__PURE__ */ new Set(["get", "put", "post", "delete", "options", "head", "patch", "trace"]);
|
|
36304
36393
|
function normalizePath(url) {
|
|
36305
36394
|
let u = (url || "").trim();
|
|
36306
36395
|
u = u.split("#")[0].split("?")[0];
|
|
36307
|
-
u = u.
|
|
36396
|
+
u = u.replaceAll(/\{\{[^}]*\}\}/g, "");
|
|
36308
36397
|
u = u.replace(/^[a-z0-9+.-]+:\/\/[^/]*/i, "");
|
|
36309
|
-
u = u.
|
|
36398
|
+
u = u.replaceAll(/\/{2,}/g, "/");
|
|
36310
36399
|
if (!u.startsWith("/")) u = "/" + u;
|
|
36311
36400
|
u = u.replace(/\/+$/, "");
|
|
36312
36401
|
return u === "" ? "/" : u;
|
|
@@ -36326,7 +36415,7 @@ function pathMatches(requestUrl, template) {
|
|
|
36326
36415
|
}
|
|
36327
36416
|
function resolveRef$2(spec2, ref) {
|
|
36328
36417
|
const parts = ref.replace(/^#\//, "").split("/");
|
|
36329
|
-
return parts.reduce((o, k) => o?.[decodeURIComponent(k.
|
|
36418
|
+
return parts.reduce((o, k) => o?.[decodeURIComponent(k.replaceAll("~1", "/").replaceAll("~0", "~"))], spec2);
|
|
36330
36419
|
}
|
|
36331
36420
|
function deref$2(spec2, node, depth = 0, seen2 = /* @__PURE__ */ new Set()) {
|
|
36332
36421
|
if (!node || typeof node !== "object" || depth > 8) return node;
|
|
@@ -36347,8 +36436,7 @@ function flattenSchemaPaths(schema, prefix2 = "", depth = 0) {
|
|
|
36347
36436
|
if (type === "object" || schema.properties) {
|
|
36348
36437
|
for (const [name, sub] of Object.entries(schema.properties ?? {})) {
|
|
36349
36438
|
const path = prefix2 ? `${prefix2}.${name}` : name;
|
|
36350
|
-
out.push(path);
|
|
36351
|
-
out.push(...flattenSchemaPaths(sub, path, depth + 1));
|
|
36439
|
+
out.push(path, ...flattenSchemaPaths(sub, path, depth + 1));
|
|
36352
36440
|
}
|
|
36353
36441
|
} else if (type === "array" && schema.items) {
|
|
36354
36442
|
out.push(...flattenSchemaPaths(schema.items, `${prefix2}[]`, depth + 1));
|
|
@@ -36363,14 +36451,13 @@ function flattenValuePaths(value2, prefix2 = "", depth = 0) {
|
|
|
36363
36451
|
} else {
|
|
36364
36452
|
for (const [k, v] of Object.entries(value2)) {
|
|
36365
36453
|
const path = prefix2 ? `${prefix2}.${k}` : k;
|
|
36366
|
-
out.push(path);
|
|
36367
|
-
out.push(...flattenValuePaths(v, path, depth + 1));
|
|
36454
|
+
out.push(path, ...flattenValuePaths(v, path, depth + 1));
|
|
36368
36455
|
}
|
|
36369
36456
|
}
|
|
36370
36457
|
return [...new Set(out)];
|
|
36371
36458
|
}
|
|
36372
36459
|
function successResponseSchema$1(spec2, responses) {
|
|
36373
|
-
const code = Object.keys(responses ?? {}).filter((c) => /^2\d\d$/.test(c)).sort()[0];
|
|
36460
|
+
const code = Object.keys(responses ?? {}).filter((c) => /^2\d\d$/.test(c)).sort((a, b) => a.localeCompare(b))[0];
|
|
36374
36461
|
if (!code) return void 0;
|
|
36375
36462
|
const schema = responses[code]?.content?.["application/json"]?.schema ?? responses[code]?.content?.["application/json;charset=utf-8"]?.schema;
|
|
36376
36463
|
return schema ? deref$2(spec2, schema) : void 0;
|
|
@@ -36381,7 +36468,7 @@ function enumerateOperations(spec2) {
|
|
|
36381
36468
|
for (const [path, item] of Object.entries(doc.paths ?? {})) {
|
|
36382
36469
|
if (!item || typeof item !== "object") continue;
|
|
36383
36470
|
for (const [method, op] of Object.entries(item)) {
|
|
36384
|
-
if (!HTTP_METHODS$2.
|
|
36471
|
+
if (!HTTP_METHODS$2.has(method.toLowerCase())) continue;
|
|
36385
36472
|
if (!op || typeof op !== "object") continue;
|
|
36386
36473
|
const declaredStatuses = Object.keys(op.responses ?? {}).filter((c) => /^\d{3}$/.test(c));
|
|
36387
36474
|
ops.push({ method: method.toUpperCase(), path, operationId: op.operationId, declaredStatuses, responses: op.responses });
|
|
@@ -36442,10 +36529,10 @@ function computeCoverage(spec2, requests, observations = []) {
|
|
|
36442
36529
|
operations: operations2
|
|
36443
36530
|
};
|
|
36444
36531
|
}
|
|
36445
|
-
const HTTP_METHODS$1 = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
36532
|
+
const HTTP_METHODS$1 = /* @__PURE__ */ new Set(["get", "put", "post", "delete", "options", "head", "patch", "trace"]);
|
|
36446
36533
|
function resolveRef$1(spec2, ref) {
|
|
36447
36534
|
const parts = ref.replace(/^#\//, "").split("/");
|
|
36448
|
-
return parts.reduce((o, k) => o?.[decodeURIComponent(k.
|
|
36535
|
+
return parts.reduce((o, k) => o?.[decodeURIComponent(k.replaceAll("~1", "/").replaceAll("~0", "~"))], spec2);
|
|
36449
36536
|
}
|
|
36450
36537
|
function deref$1(spec2, node, depth = 0, seen2 = /* @__PURE__ */ new Set()) {
|
|
36451
36538
|
if (!node || typeof node !== "object" || depth > 8) return node;
|
|
@@ -36618,7 +36705,7 @@ function generateTests(spec2, options = {}) {
|
|
|
36618
36705
|
for (const [path, item] of Object.entries(doc.paths ?? {})) {
|
|
36619
36706
|
if (!item || typeof item !== "object") continue;
|
|
36620
36707
|
for (const [method, op] of Object.entries(item)) {
|
|
36621
|
-
if (!HTTP_METHODS$1.
|
|
36708
|
+
if (!HTTP_METHODS$1.has(method.toLowerCase())) continue;
|
|
36622
36709
|
if (!op || typeof op !== "object") continue;
|
|
36623
36710
|
if (opts.only.size && !opts.only.has(`${method.toUpperCase()} ${path}`)) continue;
|
|
36624
36711
|
out.push(...generateForOperation(doc, method.toUpperCase(), path, item, op, opts));
|
|
@@ -36854,10 +36941,10 @@ function CoverageModal() {
|
|
|
36854
36941
|
}
|
|
36855
36942
|
);
|
|
36856
36943
|
}
|
|
36857
|
-
const HTTP_METHODS = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
36944
|
+
const HTTP_METHODS = /* @__PURE__ */ new Set(["get", "put", "post", "delete", "options", "head", "patch", "trace"]);
|
|
36858
36945
|
function resolveRef(spec2, ref) {
|
|
36859
36946
|
const parts = ref.replace(/^#\//, "").split("/");
|
|
36860
|
-
return parts.reduce((o, k) => o?.[decodeURIComponent(k.
|
|
36947
|
+
return parts.reduce((o, k) => o?.[decodeURIComponent(k.replaceAll("~1", "/").replaceAll("~0", "~"))], spec2);
|
|
36861
36948
|
}
|
|
36862
36949
|
function deref(spec2, node, depth = 0, seen2 = /* @__PURE__ */ new Set()) {
|
|
36863
36950
|
if (!node || typeof node !== "object" || depth > 8) return node;
|
|
@@ -36898,7 +36985,7 @@ function requestSchema(spec2, op) {
|
|
|
36898
36985
|
}
|
|
36899
36986
|
function successResponseSchema(spec2, op) {
|
|
36900
36987
|
const responses = op?.responses ?? {};
|
|
36901
|
-
const code = Object.keys(responses).filter((c) => /^2\d\d$/.test(c)).sort()[0];
|
|
36988
|
+
const code = Object.keys(responses).filter((c) => /^2\d\d$/.test(c)).sort((a, b) => a.localeCompare(b))[0];
|
|
36902
36989
|
return code ? deref(spec2, responses[code])?.content?.["application/json"]?.schema : void 0;
|
|
36903
36990
|
}
|
|
36904
36991
|
function paramRequired(spec2, pathItem, op) {
|
|
@@ -36912,7 +36999,7 @@ function operations(spec2) {
|
|
|
36912
36999
|
for (const [path, item] of Object.entries(spec2?.paths ?? {})) {
|
|
36913
37000
|
if (!item || typeof item !== "object") continue;
|
|
36914
37001
|
for (const [method, op] of Object.entries(item)) {
|
|
36915
|
-
if (!HTTP_METHODS.
|
|
37002
|
+
if (!HTTP_METHODS.has(method.toLowerCase())) continue;
|
|
36916
37003
|
map.set(`${method.toUpperCase()} ${path}`, { method: method.toUpperCase(), path, pathItem: item, op });
|
|
36917
37004
|
}
|
|
36918
37005
|
}
|
|
@@ -37116,7 +37203,7 @@ function CompareModal() {
|
|
|
37116
37203
|
);
|
|
37117
37204
|
}
|
|
37118
37205
|
function toCSV(ds) {
|
|
37119
|
-
const escape = (s) => s.includes(",") || s.includes('"') || s.includes("\n") ? `"${s.
|
|
37206
|
+
const escape = (s) => s.includes(",") || s.includes('"') || s.includes("\n") ? `"${s.replaceAll('"', '""')}"` : s;
|
|
37120
37207
|
return [ds.columns, ...ds.rows].map((row) => row.map(escape).join(",")).join("\n");
|
|
37121
37208
|
}
|
|
37122
37209
|
function parseCSV(text) {
|
|
@@ -37182,7 +37269,7 @@ function DataSetEditor({ ds, onChange, exportName, scopeLabel = "collection" })
|
|
|
37182
37269
|
const url = URL.createObjectURL(blob);
|
|
37183
37270
|
const a = document.createElement("a");
|
|
37184
37271
|
a.href = url;
|
|
37185
|
-
a.download = `${exportName.
|
|
37272
|
+
a.download = `${exportName.replaceAll(/\s+/g, "_")}_data.csv`;
|
|
37186
37273
|
a.click();
|
|
37187
37274
|
URL.revokeObjectURL(url);
|
|
37188
37275
|
}
|
|
@@ -37340,7 +37427,7 @@ function CollectionPanel() {
|
|
|
37340
37427
|
] }),
|
|
37341
37428
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex border-b border-surface-800 px-6 flex-shrink-0", children: [
|
|
37342
37429
|
{ id: "documentation", label: "Documentation", badge: col.description?.trim() ? 1 : 0 },
|
|
37343
|
-
{ id: "data", label: "Data", badge: iterCount
|
|
37430
|
+
{ id: "data", label: "Data", badge: Math.max(iterCount, 0) },
|
|
37344
37431
|
{ id: "variables", label: "Variables", badge: Object.keys(col.collectionVariables ?? {}).length }
|
|
37345
37432
|
].map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
37346
37433
|
"button",
|
|
@@ -37426,7 +37513,7 @@ function FolderPanel() {
|
|
|
37426
37513
|
] }),
|
|
37427
37514
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex border-b border-surface-800 px-6 flex-shrink-0", children: [
|
|
37428
37515
|
{ id: "documentation", label: "Documentation", badge: folder2.description?.trim() ? 1 : 0 },
|
|
37429
|
-
{ id: "data", label: "Data", badge: iterCount
|
|
37516
|
+
{ id: "data", label: "Data", badge: Math.max(iterCount, 0) },
|
|
37430
37517
|
{ id: "variables", label: "Variables", badge: varRows.length }
|
|
37431
37518
|
].map((tab) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
37432
37519
|
"button",
|
|
@@ -37594,7 +37681,7 @@ function MockPanel() {
|
|
|
37594
37681
|
await electron$9.saveMock(relPath, mock);
|
|
37595
37682
|
const ws = useStore.getState().workspace;
|
|
37596
37683
|
if (ws) {
|
|
37597
|
-
|
|
37684
|
+
ws.mocks ??= [];
|
|
37598
37685
|
ws.mocks.push(relPath);
|
|
37599
37686
|
await electron$9.saveWorkspace(ws);
|
|
37600
37687
|
}
|
|
@@ -39089,7 +39176,7 @@ function ViolationRow({ v }) {
|
|
|
39089
39176
|
const t = useT();
|
|
39090
39177
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1 px-4 py-2.5 border-l-2 border-red-600 bg-red-950/20 rounded-r", children: [
|
|
39091
39178
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
39092
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono font-bold text-red-400 uppercase tracking-wide", children: v.type.
|
|
39179
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono font-bold text-red-400 uppercase tracking-wide", children: v.type.replaceAll("_", " ") }),
|
|
39093
39180
|
v.path && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono text-surface-500 bg-surface-800 px-1.5 py-0.5 rounded", children: v.path })
|
|
39094
39181
|
] }),
|
|
39095
39182
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-red-200", children: v.message }),
|
|
@@ -39278,7 +39365,7 @@ function designContractToMock(cc, port = 4100) {
|
|
|
39278
39365
|
id: it2.id || `route-${i}`,
|
|
39279
39366
|
// Pact path templates use {id}; the mock router uses :id.
|
|
39280
39367
|
method: (it2.request.method || "GET").toUpperCase(),
|
|
39281
|
-
path: (it2.request.path || "/").
|
|
39368
|
+
path: (it2.request.path || "/").replaceAll(/\{([^}]+)\}/g, ":$1"),
|
|
39282
39369
|
statusCode: it2.response.status,
|
|
39283
39370
|
headers: { "Content-Type": "application/json", ...kvToHeaders(it2.response.headers) },
|
|
39284
39371
|
body: it2.response.body?.trim() ? it2.response.body : "",
|
|
@@ -39366,8 +39453,8 @@ function ContractDesignerModal({ seed, onClose }) {
|
|
|
39366
39453
|
...base,
|
|
39367
39454
|
...seed,
|
|
39368
39455
|
id: uid(),
|
|
39369
|
-
request: { ...base.request, ...seed.request
|
|
39370
|
-
response: { ...base.response, ...seed.response
|
|
39456
|
+
request: { ...base.request, ...seed.request },
|
|
39457
|
+
response: { ...base.response, ...seed.response }
|
|
39371
39458
|
};
|
|
39372
39459
|
const contract = { ...newContract(), interactions: [interaction] };
|
|
39373
39460
|
setSelectedId(contract.id);
|
|
@@ -39967,7 +40054,7 @@ function ConflictEditor({ path, onClose, onResolved }) {
|
|
|
39967
40054
|
}, [path]);
|
|
39968
40055
|
const conflictCount = reactExports.useMemo(() => parts?.filter((p) => p.type === "conflict").length ?? 0, [parts]);
|
|
39969
40056
|
const unresolved = reactExports.useMemo(() => parts?.filter((p) => p.type === "conflict" && !p.choice).length ?? 0, [parts]);
|
|
39970
|
-
const content = manual
|
|
40057
|
+
const content = manual ?? (parts ? assemble(parts) : "");
|
|
39971
40058
|
const stillHasMarkers = /^(<{7}|={7}|>{7})/m.test(content);
|
|
39972
40059
|
function choose(idx, choice) {
|
|
39973
40060
|
setParts((prev) => prev?.map((p, i) => i === idx && p.type === "conflict" ? { ...p, choice } : p) ?? prev);
|
|
@@ -40325,7 +40412,10 @@ function ChangesTab({ status, onRefresh }) {
|
|
|
40325
40412
|
"div",
|
|
40326
40413
|
{
|
|
40327
40414
|
className: `flex items-center gap-2 px-3 py-1 hover:bg-surface-800/50 cursor-pointer group text-xs ${diffFile === f.path && diffStaged ? "bg-surface-800" : ""}`,
|
|
40415
|
+
role: "button",
|
|
40416
|
+
tabIndex: 0,
|
|
40328
40417
|
onClick: () => showDiff(f, true),
|
|
40418
|
+
onKeyDown: onActivateKey(() => showDiff(f, true)),
|
|
40329
40419
|
children: [
|
|
40330
40420
|
/* @__PURE__ */ jsxRuntimeExports.jsx(StatusBadge, { status: f.status }),
|
|
40331
40421
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate text-surface-200", children: f.path }),
|
|
@@ -40362,7 +40452,10 @@ function ChangesTab({ status, onRefresh }) {
|
|
|
40362
40452
|
"div",
|
|
40363
40453
|
{
|
|
40364
40454
|
className: `flex items-center gap-2 px-3 py-1 hover:bg-surface-800/50 cursor-pointer group text-xs ${diffFile === f.path && !diffStaged ? "bg-surface-800" : ""}`,
|
|
40455
|
+
role: "button",
|
|
40456
|
+
tabIndex: 0,
|
|
40365
40457
|
onClick: () => showDiff(f, false),
|
|
40458
|
+
onKeyDown: onActivateKey(() => showDiff(f, false)),
|
|
40366
40459
|
children: [
|
|
40367
40460
|
/* @__PURE__ */ jsxRuntimeExports.jsx(StatusBadge, { status: f.status }),
|
|
40368
40461
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate text-surface-200", children: f.path }),
|
|
@@ -40389,7 +40482,10 @@ function ChangesTab({ status, onRefresh }) {
|
|
|
40389
40482
|
"div",
|
|
40390
40483
|
{
|
|
40391
40484
|
className: `flex items-center gap-2 px-3 py-1 hover:bg-surface-800/50 cursor-pointer group text-xs ${diffFile === path && !diffStaged ? "bg-surface-800" : ""}`,
|
|
40485
|
+
role: "button",
|
|
40486
|
+
tabIndex: 0,
|
|
40392
40487
|
onClick: () => showDiff({ path, status: "modified" }, false),
|
|
40488
|
+
onKeyDown: onActivateKey(() => showDiff({ path, status: "modified" }, false)),
|
|
40393
40489
|
children: [
|
|
40394
40490
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[11px] font-bold w-4 shrink-0 text-red-400", children: "!" }),
|
|
40395
40491
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate text-red-300", children: path }),
|
|
@@ -41117,10 +41213,16 @@ function CommandPalette() {
|
|
|
41117
41213
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "max-h-80 overflow-y-auto", children: filtered2.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-6 text-center text-sm text-surface-600", children: t('No requests match ":query"', { query }) }) : filtered2.map((item, idx) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
41118
41214
|
"div",
|
|
41119
41215
|
{
|
|
41216
|
+
role: "button",
|
|
41217
|
+
tabIndex: 0,
|
|
41120
41218
|
onClick: () => {
|
|
41121
41219
|
openInTab(item.requestId, item.collectionId);
|
|
41122
41220
|
setOpen(false);
|
|
41123
41221
|
},
|
|
41222
|
+
onKeyDown: onActivateKey(() => {
|
|
41223
|
+
openInTab(item.requestId, item.collectionId);
|
|
41224
|
+
setOpen(false);
|
|
41225
|
+
}),
|
|
41124
41226
|
onMouseEnter: () => setActiveIdx(idx),
|
|
41125
41227
|
className: `flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${idx === activeIdx ? "bg-surface-800" : "hover:bg-surface-800/50"}`,
|
|
41126
41228
|
children: [
|
|
@@ -41279,7 +41381,10 @@ const TabRow = React$2.memo(function TabRow2({
|
|
|
41279
41381
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
41280
41382
|
"div",
|
|
41281
41383
|
{
|
|
41384
|
+
role: "button",
|
|
41385
|
+
tabIndex: 0,
|
|
41282
41386
|
onClick: () => onActivate(tabId),
|
|
41387
|
+
onKeyDown: onActivateKey(() => onActivate(tabId)),
|
|
41283
41388
|
onContextMenu: (e) => {
|
|
41284
41389
|
e.preventDefault();
|
|
41285
41390
|
onContextMenu(tabId, e.clientX, e.clientY);
|
|
@@ -41485,7 +41590,7 @@ function App() {
|
|
|
41485
41590
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "#6aa3c8" }, children: "Spector" }),
|
|
41486
41591
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-2 text-[10px] font-normal opacity-50", children: [
|
|
41487
41592
|
"v",
|
|
41488
|
-
"0.6.
|
|
41593
|
+
"0.6.4"
|
|
41489
41594
|
] }),
|
|
41490
41595
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mx-2 opacity-30", children: "·" }),
|
|
41491
41596
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -41584,13 +41689,27 @@ function App() {
|
|
|
41584
41689
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
41585
41690
|
"div",
|
|
41586
41691
|
{
|
|
41587
|
-
|
|
41692
|
+
role: "separator",
|
|
41693
|
+
"aria-orientation": "vertical",
|
|
41694
|
+
"aria-label": "Resize sidebar",
|
|
41695
|
+
"aria-valuemin": 160,
|
|
41696
|
+
"aria-valuemax": 520,
|
|
41697
|
+
"aria-valuenow": sidebarWidth,
|
|
41698
|
+
tabIndex: 0,
|
|
41699
|
+
className: "flex-shrink-0 w-1 cursor-col-resize border-r border-surface-800 hover:border-blue-500 focus:border-blue-500 focus:outline-none transition-colors",
|
|
41588
41700
|
onMouseDown: (e) => {
|
|
41589
41701
|
dragging.current = "sidebar";
|
|
41590
41702
|
dragStart.current = { x: e.clientX, w: sidebarWidth };
|
|
41591
41703
|
document.body.style.cursor = "col-resize";
|
|
41592
41704
|
document.body.style.userSelect = "none";
|
|
41593
41705
|
e.preventDefault();
|
|
41706
|
+
},
|
|
41707
|
+
onKeyDown: (e) => {
|
|
41708
|
+
if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
|
|
41709
|
+
e.preventDefault();
|
|
41710
|
+
const step = e.key === "ArrowLeft" ? -16 : 16;
|
|
41711
|
+
setSidebarWidth((w) => Math.max(160, Math.min(520, w + step)));
|
|
41712
|
+
}
|
|
41594
41713
|
}
|
|
41595
41714
|
}
|
|
41596
41715
|
)
|
|
@@ -41636,8 +41755,14 @@ function App() {
|
|
|
41636
41755
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
41637
41756
|
"div",
|
|
41638
41757
|
{
|
|
41758
|
+
role: "button",
|
|
41759
|
+
tabIndex: -1,
|
|
41760
|
+
"aria-label": t("Close menu"),
|
|
41639
41761
|
className: "fixed inset-0 z-40",
|
|
41640
41762
|
onClick: () => setTabContextMenu(null),
|
|
41763
|
+
onKeyDown: (e) => {
|
|
41764
|
+
if (e.key === "Escape") setTabContextMenu(null);
|
|
41765
|
+
},
|
|
41641
41766
|
onContextMenu: (e) => {
|
|
41642
41767
|
e.preventDefault();
|
|
41643
41768
|
setTabContextMenu(null);
|
|
@@ -41713,7 +41838,7 @@ function App() {
|
|
|
41713
41838
|
await electron.saveMock(relPath, newRoutes);
|
|
41714
41839
|
const ws = useStore.getState().workspace;
|
|
41715
41840
|
if (ws) {
|
|
41716
|
-
|
|
41841
|
+
ws.mocks ??= [];
|
|
41717
41842
|
ws.mocks.push(relPath);
|
|
41718
41843
|
await electron.saveWorkspace(ws);
|
|
41719
41844
|
}
|
|
@@ -41735,7 +41860,13 @@ function App() {
|
|
|
41735
41860
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
41736
41861
|
"div",
|
|
41737
41862
|
{
|
|
41738
|
-
|
|
41863
|
+
role: "separator",
|
|
41864
|
+
"aria-orientation": "vertical",
|
|
41865
|
+
"aria-label": "Resize request pane",
|
|
41866
|
+
"aria-valuemin": 200,
|
|
41867
|
+
"aria-valuenow": requestPaneWidth ?? leftPaneRef.current?.offsetWidth ?? 400,
|
|
41868
|
+
tabIndex: 0,
|
|
41869
|
+
className: "flex-shrink-0 w-1 relative cursor-col-resize border-x border-surface-800 hover:border-blue-500 focus:border-blue-500 focus:outline-none transition-colors group",
|
|
41739
41870
|
onMouseDown: (e) => {
|
|
41740
41871
|
dragging.current = "request";
|
|
41741
41872
|
dragStart.current = { x: e.clientX, w: leftPaneRef.current?.offsetWidth ?? requestPaneWidth ?? 400 };
|
|
@@ -41743,6 +41874,14 @@ function App() {
|
|
|
41743
41874
|
document.body.style.userSelect = "none";
|
|
41744
41875
|
e.preventDefault();
|
|
41745
41876
|
},
|
|
41877
|
+
onKeyDown: (e) => {
|
|
41878
|
+
if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
|
|
41879
|
+
e.preventDefault();
|
|
41880
|
+
const step = e.key === "ArrowLeft" ? -16 : 16;
|
|
41881
|
+
const cur = leftPaneRef.current?.offsetWidth ?? requestPaneWidth ?? 400;
|
|
41882
|
+
setRequestPaneWidth(Math.max(200, Math.min(window.innerWidth - 300, cur + step)));
|
|
41883
|
+
}
|
|
41884
|
+
},
|
|
41746
41885
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
41747
41886
|
"button",
|
|
41748
41887
|
{
|
|
@@ -41782,7 +41921,7 @@ if (savedTheme === "light") {
|
|
|
41782
41921
|
}
|
|
41783
41922
|
}
|
|
41784
41923
|
const savedZoom = localStorage.getItem(STORAGE_KEYS.zoom);
|
|
41785
|
-
if (savedZoom) window.electron.setZoomFactor(parseFloat(savedZoom));
|
|
41924
|
+
if (savedZoom) window.electron.setZoomFactor(Number.parseFloat(savedZoom));
|
|
41786
41925
|
ReactDOM.createRoot(document.getElementById("root")).render(
|
|
41787
41926
|
/* @__PURE__ */ jsxRuntimeExports.jsx(React$2.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(I18nProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBoundary, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(App, {}) }) }) })
|
|
41788
41927
|
);
|