@testsmith/api-spector 0.4.5 → 0.4.7
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 +2 -1
- package/out/main/chunks/{cli-common-CDQY1erJ.js → cli-common-BKYgsbGB.js} +1 -0
- package/out/main/chunks/{handle-BGYDylL2.js → handle-rimXXdJH.js} +26 -1
- package/out/main/chunks/{import-CUcjlmSK.js → import-DcenB5Q_.js} +2 -2
- package/out/main/chunks/{mock-server-DSLR2ulH.js → mock-server-BxiXhP1m.js} +2 -0
- package/out/main/chunks/{request-exec-DQfwItAd.js → request-exec-BH-M3KqZ.js} +204 -6
- package/out/main/chunks/{snapshots-Bm60eRRj.js → snapshots-CtYxkSLz.js} +556 -6
- package/out/main/chunks/{soap-handler-CAyUjzxB.js → soap-handler-BXx842MN.js} +2 -2
- package/out/main/contract.js +265 -296
- package/out/main/index.js +366 -20
- package/out/main/lib.js +37 -0
- package/out/main/mock.js +2 -2
- package/out/main/record.js +1 -1
- package/out/main/runner.js +4 -4
- package/out/main/wsdl.js +5 -4
- package/out/preload/index.js +45 -1
- package/out/renderer/assets/{index-CjLzO0tH.js → index-B-OQJk1G.js} +2609 -787
- package/out/renderer/assets/index-B_xyaTDo.css +2 -0
- package/out/renderer/index.html +2 -2
- package/package.json +13 -5
- package/out/renderer/assets/index-DkZ0bxof.css +0 -2
|
@@ -2515,11 +2515,11 @@ function constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) {
|
|
|
2515
2515
|
nativeEventTarget
|
|
2516
2516
|
), dispatchQueue.push({ event: nativeEvent, listeners: doc2 }), nativeEvent.target = activeElement)));
|
|
2517
2517
|
}
|
|
2518
|
-
function makePrefixMap(styleProp,
|
|
2518
|
+
function makePrefixMap(styleProp, eventName2) {
|
|
2519
2519
|
var prefixes = {};
|
|
2520
|
-
prefixes[styleProp.toLowerCase()] =
|
|
2521
|
-
prefixes["Webkit" + styleProp] = "webkit" +
|
|
2522
|
-
prefixes["Moz" + styleProp] = "moz" +
|
|
2520
|
+
prefixes[styleProp.toLowerCase()] = eventName2.toLowerCase();
|
|
2521
|
+
prefixes["Webkit" + styleProp] = "webkit" + eventName2;
|
|
2522
|
+
prefixes["Moz" + styleProp] = "moz" + eventName2;
|
|
2523
2523
|
return prefixes;
|
|
2524
2524
|
}
|
|
2525
2525
|
var vendorPrefixes = {
|
|
@@ -2532,14 +2532,14 @@ var vendorPrefixes = {
|
|
|
2532
2532
|
transitionend: makePrefixMap("Transition", "TransitionEnd")
|
|
2533
2533
|
}, prefixedEventNames = {}, style = {};
|
|
2534
2534
|
canUseDOM && (style = document.createElement("div").style, "AnimationEvent" in window || (delete vendorPrefixes.animationend.animation, delete vendorPrefixes.animationiteration.animation, delete vendorPrefixes.animationstart.animation), "TransitionEvent" in window || delete vendorPrefixes.transitionend.transition);
|
|
2535
|
-
function getVendorPrefixedEventName(
|
|
2536
|
-
if (prefixedEventNames[
|
|
2537
|
-
if (!vendorPrefixes[
|
|
2538
|
-
var prefixMap = vendorPrefixes[
|
|
2535
|
+
function getVendorPrefixedEventName(eventName2) {
|
|
2536
|
+
if (prefixedEventNames[eventName2]) return prefixedEventNames[eventName2];
|
|
2537
|
+
if (!vendorPrefixes[eventName2]) return eventName2;
|
|
2538
|
+
var prefixMap = vendorPrefixes[eventName2], styleProp;
|
|
2539
2539
|
for (styleProp in prefixMap)
|
|
2540
2540
|
if (prefixMap.hasOwnProperty(styleProp) && styleProp in style)
|
|
2541
|
-
return prefixedEventNames[
|
|
2542
|
-
return
|
|
2541
|
+
return prefixedEventNames[eventName2] = prefixMap[styleProp];
|
|
2542
|
+
return eventName2;
|
|
2543
2543
|
}
|
|
2544
2544
|
var ANIMATION_END = getVendorPrefixedEventName("animationend"), ANIMATION_ITERATION = getVendorPrefixedEventName("animationiteration"), ANIMATION_START = getVendorPrefixedEventName("animationstart"), TRANSITION_RUN = getVendorPrefixedEventName("transitionrun"), TRANSITION_START = getVendorPrefixedEventName("transitionstart"), TRANSITION_CANCEL = getVendorPrefixedEventName("transitioncancel"), TRANSITION_END = getVendorPrefixedEventName("transitionend"), topLevelEventsToReactNames = /* @__PURE__ */ new Map(), simpleEventPluginEvents = "abort auxClick beforeToggle cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(
|
|
2545
2545
|
" "
|
|
@@ -13403,6 +13403,25 @@ const createWsSlice = (set2) => ({
|
|
|
13403
13403
|
if (s.wsConnections[requestId]) s.wsConnections[requestId].messages = [];
|
|
13404
13404
|
})
|
|
13405
13405
|
});
|
|
13406
|
+
const LIVE_EVENT_CAP = 5e3;
|
|
13407
|
+
const createStreamSlice = (set2) => ({
|
|
13408
|
+
liveStream: null,
|
|
13409
|
+
startLiveStream: (tabId, streamId) => set2((s) => {
|
|
13410
|
+
s.liveStream = { streamId, tabId, events: [], streaming: true };
|
|
13411
|
+
}),
|
|
13412
|
+
pushLiveStreamEvents: (streamId, events) => set2((s) => {
|
|
13413
|
+
if (!s.liveStream || s.liveStream.streamId !== streamId) return;
|
|
13414
|
+
s.liveStream.events.push(...events);
|
|
13415
|
+
const overflow = s.liveStream.events.length - LIVE_EVENT_CAP;
|
|
13416
|
+
if (overflow > 0) s.liveStream.events.splice(0, overflow);
|
|
13417
|
+
}),
|
|
13418
|
+
finishLiveStream: (streamId) => set2((s) => {
|
|
13419
|
+
if (s.liveStream?.streamId === streamId) s.liveStream.streaming = false;
|
|
13420
|
+
}),
|
|
13421
|
+
clearLiveStream: (tabId) => set2((s) => {
|
|
13422
|
+
if (s.liveStream?.tabId === tabId) s.liveStream = null;
|
|
13423
|
+
})
|
|
13424
|
+
});
|
|
13406
13425
|
const HISTORY_CAP = 200;
|
|
13407
13426
|
let saveTimer = null;
|
|
13408
13427
|
function persistIfEnabled(get2) {
|
|
@@ -13508,6 +13527,7 @@ function makeTab(requestId, collectionId, opts = {}) {
|
|
|
13508
13527
|
return {
|
|
13509
13528
|
id: v4(),
|
|
13510
13529
|
requestId,
|
|
13530
|
+
exampleId: opts.exampleId ?? null,
|
|
13511
13531
|
collectionId,
|
|
13512
13532
|
lastResponse: null,
|
|
13513
13533
|
lastScriptResult: null,
|
|
@@ -13536,7 +13556,7 @@ const createTabsSlice = (set2, get2) => ({
|
|
|
13536
13556
|
activeCollectionId: null,
|
|
13537
13557
|
openInTab: (requestId, collectionId) => set2((s) => {
|
|
13538
13558
|
s.collectionPanelOpen = false;
|
|
13539
|
-
const existing = s.tabs.find((t2) => t2.requestId === requestId);
|
|
13559
|
+
const existing = s.tabs.find((t2) => t2.requestId === requestId && !t2.exampleId);
|
|
13540
13560
|
if (existing) {
|
|
13541
13561
|
s.activeTabId = existing.id;
|
|
13542
13562
|
s.activeCollectionId = collectionId;
|
|
@@ -13853,6 +13873,117 @@ const createCollectionsSlice = (set2, get2) => ({
|
|
|
13853
13873
|
Object.assign(entry.data.requests[id2], patch);
|
|
13854
13874
|
entry.dirty = true;
|
|
13855
13875
|
}),
|
|
13876
|
+
// ── Request examples ────────────────────────────────────────────────────────
|
|
13877
|
+
addExample: (requestId, snapshot) => {
|
|
13878
|
+
const id2 = v4();
|
|
13879
|
+
set2((s) => {
|
|
13880
|
+
const entry = Object.values(s.collections).find((c) => c.data.requests[requestId]);
|
|
13881
|
+
if (!entry) return;
|
|
13882
|
+
const req = entry.data.requests[requestId];
|
|
13883
|
+
const list2 = req.examples ?? (req.examples = []);
|
|
13884
|
+
const example = {
|
|
13885
|
+
id: id2,
|
|
13886
|
+
name: snapshot.name || uniqueName("Example", list2.map((e) => e.name)),
|
|
13887
|
+
request: snapshot.request,
|
|
13888
|
+
response: snapshot.response ?? null,
|
|
13889
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13890
|
+
source: "saved"
|
|
13891
|
+
};
|
|
13892
|
+
list2.push(example);
|
|
13893
|
+
entry.dirty = true;
|
|
13894
|
+
});
|
|
13895
|
+
return id2;
|
|
13896
|
+
},
|
|
13897
|
+
addExampleFromRequest: (requestId) => {
|
|
13898
|
+
const entry = Object.values(get2().collections).find((c) => c.data.requests[requestId]);
|
|
13899
|
+
if (!entry) return null;
|
|
13900
|
+
const req = entry.data.requests[requestId];
|
|
13901
|
+
const id2 = v4();
|
|
13902
|
+
const example = {
|
|
13903
|
+
id: id2,
|
|
13904
|
+
name: uniqueName("Example", (req.examples ?? []).map((e) => e.name)),
|
|
13905
|
+
request: {
|
|
13906
|
+
method: req.method,
|
|
13907
|
+
url: req.url,
|
|
13908
|
+
headers: structuredClone(req.headers),
|
|
13909
|
+
params: structuredClone(req.params),
|
|
13910
|
+
auth: structuredClone(req.auth),
|
|
13911
|
+
body: structuredClone(req.body)
|
|
13912
|
+
},
|
|
13913
|
+
response: null,
|
|
13914
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13915
|
+
source: "saved"
|
|
13916
|
+
};
|
|
13917
|
+
set2((s) => {
|
|
13918
|
+
const e = Object.values(s.collections).find((c) => c.data.requests[requestId]);
|
|
13919
|
+
if (!e) return;
|
|
13920
|
+
const r = e.data.requests[requestId];
|
|
13921
|
+
(r.examples ?? (r.examples = [])).push(example);
|
|
13922
|
+
e.dirty = true;
|
|
13923
|
+
});
|
|
13924
|
+
return id2;
|
|
13925
|
+
},
|
|
13926
|
+
updateExampleRequest: (requestId, exampleId, patch) => set2((s) => {
|
|
13927
|
+
const entry = Object.values(s.collections).find((c) => c.data.requests[requestId]);
|
|
13928
|
+
const ex = entry?.data.requests[requestId].examples?.find((e) => e.id === exampleId);
|
|
13929
|
+
if (!entry || !ex) return;
|
|
13930
|
+
ex.request = { ...ex.request ?? {}, ...patch };
|
|
13931
|
+
entry.dirty = true;
|
|
13932
|
+
}),
|
|
13933
|
+
updateExampleResponse: (requestId, exampleId, response) => set2((s) => {
|
|
13934
|
+
const entry = Object.values(s.collections).find((c) => c.data.requests[requestId]);
|
|
13935
|
+
const ex = entry?.data.requests[requestId].examples?.find((e) => e.id === exampleId);
|
|
13936
|
+
if (!entry || !ex) return;
|
|
13937
|
+
ex.response = response;
|
|
13938
|
+
entry.dirty = true;
|
|
13939
|
+
}),
|
|
13940
|
+
renameExample: (requestId, exampleId, name2) => set2((s) => {
|
|
13941
|
+
const entry = Object.values(s.collections).find((c) => c.data.requests[requestId]);
|
|
13942
|
+
const ex = entry?.data.requests[requestId].examples?.find((e) => e.id === exampleId);
|
|
13943
|
+
if (!entry || !ex) return;
|
|
13944
|
+
ex.name = name2;
|
|
13945
|
+
entry.dirty = true;
|
|
13946
|
+
}),
|
|
13947
|
+
deleteExample: (requestId, exampleId) => set2((s) => {
|
|
13948
|
+
const entry = Object.values(s.collections).find((c) => c.data.requests[requestId]);
|
|
13949
|
+
const req = entry?.data.requests[requestId];
|
|
13950
|
+
if (!entry || !req?.examples) return;
|
|
13951
|
+
req.examples = req.examples.filter((e) => e.id !== exampleId);
|
|
13952
|
+
entry.dirty = true;
|
|
13953
|
+
const idx = s.tabs.findIndex((t2) => t2.requestId === requestId && t2.exampleId === exampleId);
|
|
13954
|
+
if (idx !== -1) {
|
|
13955
|
+
const wasActive = s.tabs[idx].id === s.activeTabId;
|
|
13956
|
+
s.tabs.splice(idx, 1);
|
|
13957
|
+
if (wasActive) s.activeTabId = (s.tabs[idx] ?? s.tabs[idx - 1] ?? null)?.id ?? null;
|
|
13958
|
+
}
|
|
13959
|
+
}),
|
|
13960
|
+
duplicateExample: (requestId, exampleId) => set2((s) => {
|
|
13961
|
+
const entry = Object.values(s.collections).find((c) => c.data.requests[requestId]);
|
|
13962
|
+
const list2 = entry?.data.requests[requestId].examples;
|
|
13963
|
+
const ex = list2?.find((e) => e.id === exampleId);
|
|
13964
|
+
if (!entry || !list2 || !ex) return;
|
|
13965
|
+
list2.push({
|
|
13966
|
+
...structuredClone(ex),
|
|
13967
|
+
id: v4(),
|
|
13968
|
+
name: uniqueName(ex.name, list2.map((e) => e.name)),
|
|
13969
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13970
|
+
});
|
|
13971
|
+
entry.dirty = true;
|
|
13972
|
+
}),
|
|
13973
|
+
openExample: (requestId, collectionId, exampleId) => set2((s) => {
|
|
13974
|
+
const existing = s.tabs.find((t2) => t2.requestId === requestId && t2.exampleId === exampleId);
|
|
13975
|
+
if (existing) {
|
|
13976
|
+
s.activeTabId = existing.id;
|
|
13977
|
+
s.activeCollectionId = collectionId;
|
|
13978
|
+
return;
|
|
13979
|
+
}
|
|
13980
|
+
const ex = Object.values(s.collections).find((c) => c.data.requests[requestId])?.data.requests[requestId].examples?.find((e) => e.id === exampleId);
|
|
13981
|
+
const tab = makeTab(requestId, collectionId, { protocol: protocolFor(s, requestId), exampleId });
|
|
13982
|
+
tab.lastResponse = ex?.response ?? null;
|
|
13983
|
+
s.tabs.push(tab);
|
|
13984
|
+
s.activeTabId = tab.id;
|
|
13985
|
+
s.activeCollectionId = collectionId;
|
|
13986
|
+
}),
|
|
13856
13987
|
renameRequest: (id2, name2) => set2((s) => {
|
|
13857
13988
|
const entry = Object.values(s.collections).find((c) => c.data.requests[id2]);
|
|
13858
13989
|
if (!entry) return;
|
|
@@ -14206,6 +14337,7 @@ const useStore = create()(
|
|
|
14206
14337
|
immer((set2, get2, api) => ({
|
|
14207
14338
|
// ── Slice composition ─────────────────────────────────────────────────────
|
|
14208
14339
|
...createWsSlice(set2),
|
|
14340
|
+
...createStreamSlice(set2),
|
|
14209
14341
|
...createHistorySlice(set2, get2),
|
|
14210
14342
|
...createRunnerSlice(set2),
|
|
14211
14343
|
...createRecorderSlice(set2),
|
|
@@ -14298,7 +14430,7 @@ const useStore = create()(
|
|
|
14298
14430
|
})
|
|
14299
14431
|
}))
|
|
14300
14432
|
);
|
|
14301
|
-
const { electron: electron$
|
|
14433
|
+
const { electron: electron$v } = window;
|
|
14302
14434
|
function useAutoSave() {
|
|
14303
14435
|
const collections = useStore((s) => s.collections);
|
|
14304
14436
|
useStore((s) => s.environments);
|
|
@@ -14314,7 +14446,7 @@ function useAutoSave() {
|
|
|
14314
14446
|
for (const { relPath, data, dirty } of dirtyCollections) {
|
|
14315
14447
|
if (!dirty) continue;
|
|
14316
14448
|
try {
|
|
14317
|
-
await electron$
|
|
14449
|
+
await electron$v.saveCollection(relPath, data);
|
|
14318
14450
|
markCollectionClean(data.id);
|
|
14319
14451
|
} catch (e) {
|
|
14320
14452
|
console.error("Auto-save failed for", relPath, e);
|
|
@@ -14330,7 +14462,7 @@ function useAutoSave() {
|
|
|
14330
14462
|
if (wsTimerRef.current) clearTimeout(wsTimerRef.current);
|
|
14331
14463
|
wsTimerRef.current = setTimeout(async () => {
|
|
14332
14464
|
try {
|
|
14333
|
-
await electron$
|
|
14465
|
+
await electron$v.saveWorkspace(workspace);
|
|
14334
14466
|
} catch {
|
|
14335
14467
|
}
|
|
14336
14468
|
}, 300);
|
|
@@ -14339,7 +14471,7 @@ function useAutoSave() {
|
|
|
14339
14471
|
};
|
|
14340
14472
|
}, [workspace]);
|
|
14341
14473
|
}
|
|
14342
|
-
const { electron: electron$
|
|
14474
|
+
const { electron: electron$u } = window;
|
|
14343
14475
|
function useWorkspaceLoader() {
|
|
14344
14476
|
const loadCollection = useStore((s) => s.loadCollection);
|
|
14345
14477
|
const loadEnvironment = useStore((s) => s.loadEnvironment);
|
|
@@ -14363,7 +14495,7 @@ function useWorkspaceLoader() {
|
|
|
14363
14495
|
if (typeof ws2.settings?.zoom === "number") setZoom(ws2.settings.zoom);
|
|
14364
14496
|
if (ws2.settings?.persistHistory) {
|
|
14365
14497
|
try {
|
|
14366
|
-
const entries = await electron$
|
|
14498
|
+
const entries = await electron$u.loadHistory();
|
|
14367
14499
|
useStore.getState().setHistory(entries);
|
|
14368
14500
|
} catch {
|
|
14369
14501
|
}
|
|
@@ -14372,14 +14504,14 @@ function useWorkspaceLoader() {
|
|
|
14372
14504
|
}
|
|
14373
14505
|
for (const colPath of ws2.collections ?? []) {
|
|
14374
14506
|
try {
|
|
14375
|
-
const col = await electron$
|
|
14507
|
+
const col = await electron$u.loadCollection(colPath);
|
|
14376
14508
|
loadCollection(colPath, col);
|
|
14377
14509
|
} catch {
|
|
14378
14510
|
}
|
|
14379
14511
|
}
|
|
14380
14512
|
for (const envPath of ws2.environments ?? []) {
|
|
14381
14513
|
try {
|
|
14382
|
-
const env = await electron$
|
|
14514
|
+
const env = await electron$u.loadEnvironment(envPath);
|
|
14383
14515
|
loadEnvironment(envPath, env);
|
|
14384
14516
|
} catch {
|
|
14385
14517
|
}
|
|
@@ -14398,19 +14530,19 @@ function useWorkspaceLoader() {
|
|
|
14398
14530
|
}
|
|
14399
14531
|
for (const relPath of ws2.mocks ?? []) {
|
|
14400
14532
|
try {
|
|
14401
|
-
const mockData = await electron$
|
|
14533
|
+
const mockData = await electron$u.loadMock(relPath);
|
|
14402
14534
|
loadMock(relPath, mockData);
|
|
14403
14535
|
} catch {
|
|
14404
14536
|
}
|
|
14405
14537
|
}
|
|
14406
14538
|
try {
|
|
14407
|
-
const snapshots = await electron$
|
|
14539
|
+
const snapshots = await electron$u.listContractSnapshots(ws2.contracts ?? []);
|
|
14408
14540
|
for (const { relPath, snapshot } of snapshots) loadContractSnapshot(relPath, snapshot);
|
|
14409
14541
|
} catch {
|
|
14410
14542
|
}
|
|
14411
14543
|
if ((ws2.collections ?? []).length > 0) {
|
|
14412
14544
|
try {
|
|
14413
|
-
const firstCol = await electron$
|
|
14545
|
+
const firstCol = await electron$u.loadCollection(ws2.collections[0]);
|
|
14414
14546
|
setActiveCollection(firstCol.id);
|
|
14415
14547
|
} catch {
|
|
14416
14548
|
}
|
|
@@ -34460,6 +34592,81 @@ const HEADERS_METHODS = [
|
|
|
34460
34592
|
{ label: "get", type: "function", detail: "(name)", info: "Get a header value by name (case-insensitive)" },
|
|
34461
34593
|
{ label: "toObject", type: "function", detail: "()", info: "Return all headers as a plain object" }
|
|
34462
34594
|
];
|
|
34595
|
+
const CHAI_METHODS = [
|
|
34596
|
+
{ label: "equal", type: "function", detail: "(value)", info: "Strict (===) equality" },
|
|
34597
|
+
{ label: "eql", type: "function", detail: "(value)", info: "Deep equality" },
|
|
34598
|
+
{ label: "include", type: "function", detail: "(value)", info: "Target includes value (string / array / object)" },
|
|
34599
|
+
{ label: "contain", type: "function", detail: "(value)", info: "Alias of include" },
|
|
34600
|
+
{ label: "match", type: "function", detail: "(regexp)", info: "String matches a regular expression" },
|
|
34601
|
+
{ label: "above", type: "function", detail: "(n)", info: "Greater than n" },
|
|
34602
|
+
{ label: "below", type: "function", detail: "(n)", info: "Less than n" },
|
|
34603
|
+
{ label: "least", type: "function", detail: "(n)", info: "Greater than or equal to n" },
|
|
34604
|
+
{ label: "most", type: "function", detail: "(n)", info: "Less than or equal to n" },
|
|
34605
|
+
{ label: "within", type: "function", detail: "(min, max)", info: "Number within an inclusive range" },
|
|
34606
|
+
{ label: "closeTo", type: "function", detail: "(expected, delta)", info: "Number close to expected within delta" },
|
|
34607
|
+
{ label: "a", type: "function", detail: "(type)", info: "Type check, e.g. .to.be.a('string')" },
|
|
34608
|
+
{ label: "an", type: "function", detail: "(type)", info: "Type check, e.g. .to.be.an('array')" },
|
|
34609
|
+
{ label: "property", type: "function", detail: "(name, [value])", info: "Object has a property (optionally equal to value)" },
|
|
34610
|
+
{ label: "lengthOf", type: "function", detail: "(n)", info: "Array / string length equals n" },
|
|
34611
|
+
{ label: "keys", type: "function", detail: "(...keys)", info: "Object has the given keys" },
|
|
34612
|
+
{ label: "members", type: "function", detail: "(array)", info: "Array has the given members" },
|
|
34613
|
+
{ label: "oneOf", type: "function", detail: "(array)", info: "Value is one of the array" },
|
|
34614
|
+
{ label: "throw", type: "function", detail: "([error])", info: "Function throws" },
|
|
34615
|
+
{ label: "satisfy", type: "function", detail: "(fn)", info: "Value satisfies a predicate" }
|
|
34616
|
+
];
|
|
34617
|
+
const CHAI_GETTERS = [
|
|
34618
|
+
{ label: "true", type: "property", info: "Value is true" },
|
|
34619
|
+
{ label: "false", type: "property", info: "Value is false" },
|
|
34620
|
+
{ label: "null", type: "property", info: "Value is null" },
|
|
34621
|
+
{ label: "undefined", type: "property", info: "Value is undefined" },
|
|
34622
|
+
{ label: "NaN", type: "property", info: "Value is NaN" },
|
|
34623
|
+
{ label: "ok", type: "property", info: "Value is truthy" },
|
|
34624
|
+
{ label: "empty", type: "property", info: "Array / string / object is empty" },
|
|
34625
|
+
{ label: "exist", type: "property", info: "Value is neither null nor undefined" }
|
|
34626
|
+
];
|
|
34627
|
+
const chaiWords = (words) => words.map((w) => ({ label: w, type: "property", info: "Chai chain" }));
|
|
34628
|
+
const chaiPick = (labels) => CHAI_METHODS.filter((c) => labels.includes(c.label));
|
|
34629
|
+
const CHAI_AFTER = {
|
|
34630
|
+
"": [...chaiWords(["to", "not"]), ...chaiPick(["equal"])],
|
|
34631
|
+
// right after expect(...)
|
|
34632
|
+
to: [...chaiWords(["be", "have", "include", "deep", "not", "a", "an"]), ...CHAI_METHODS],
|
|
34633
|
+
not: [...chaiWords(["be", "have", "include", "deep", "a", "an"]), ...CHAI_METHODS],
|
|
34634
|
+
be: [...CHAI_GETTERS, ...chaiPick(["above", "below", "within", "a", "an", "oneOf", "closeTo", "empty"])],
|
|
34635
|
+
been: [...CHAI_GETTERS, ...chaiPick(["above", "below", "within"])],
|
|
34636
|
+
have: chaiPick(["property", "lengthOf", "keys", "members"]),
|
|
34637
|
+
has: chaiPick(["property", "lengthOf", "keys", "members"]),
|
|
34638
|
+
deep: chaiPick(["equal", "include", "members", "property"])
|
|
34639
|
+
};
|
|
34640
|
+
const CHAI_DEFAULT = [
|
|
34641
|
+
...chaiWords(["to", "be", "have", "include", "not", "deep"]),
|
|
34642
|
+
...CHAI_METHODS,
|
|
34643
|
+
...CHAI_GETTERS
|
|
34644
|
+
];
|
|
34645
|
+
function chaiChainCompletion(textBefore, pos) {
|
|
34646
|
+
const start = textBefore.lastIndexOf("sp.expect(");
|
|
34647
|
+
if (start === -1) return null;
|
|
34648
|
+
let depth = 0, close = -1;
|
|
34649
|
+
for (let i = start + "sp.expect".length; i < textBefore.length; i++) {
|
|
34650
|
+
const ch = textBefore[i];
|
|
34651
|
+
if (ch === "(") depth++;
|
|
34652
|
+
else if (ch === ")") {
|
|
34653
|
+
depth--;
|
|
34654
|
+
if (depth === 0) {
|
|
34655
|
+
close = i;
|
|
34656
|
+
break;
|
|
34657
|
+
}
|
|
34658
|
+
}
|
|
34659
|
+
}
|
|
34660
|
+
if (close === -1) return null;
|
|
34661
|
+
const chain = textBefore.slice(close + 1);
|
|
34662
|
+
const m = /^((?:\.\w+)*)\.(\w*)$/.exec(chain);
|
|
34663
|
+
if (!m) return null;
|
|
34664
|
+
const priorWords = m[1] ? m[1].split(".").filter(Boolean) : [];
|
|
34665
|
+
const lastWord = priorWords.length ? priorWords[priorWords.length - 1] : "";
|
|
34666
|
+
const partial = m[2].toLowerCase();
|
|
34667
|
+
const options = (CHAI_AFTER[lastWord] ?? CHAI_DEFAULT).filter((o) => o.label.toLowerCase().includes(partial));
|
|
34668
|
+
return { from: pos - m[2].length, options, validFor: /^\w*$/ };
|
|
34669
|
+
}
|
|
34463
34670
|
const FAKER_NAMESPACES = [
|
|
34464
34671
|
{ label: "string", type: "property", info: "String generators" },
|
|
34465
34672
|
{ label: "number", type: "property", info: "Number generators" },
|
|
@@ -34597,6 +34804,8 @@ function makeAtCompletionSource(varNames) {
|
|
|
34597
34804
|
validFor: /^\w*$/
|
|
34598
34805
|
};
|
|
34599
34806
|
}
|
|
34807
|
+
const chai = chaiChainCompletion(textBefore, context.pos);
|
|
34808
|
+
if (chai) return chai;
|
|
34600
34809
|
const headersMatch = /\bsp\.response\.headers\.(\w*)$/.exec(textBefore);
|
|
34601
34810
|
if (headersMatch) {
|
|
34602
34811
|
return { from: context.pos - headersMatch[1].length, options: HEADERS_METHODS, validFor: /^\w*$/ };
|
|
@@ -36219,7 +36428,7 @@ function CollectionSettingsModal({ collection, onClose }) {
|
|
|
36219
36428
|
}
|
|
36220
36429
|
);
|
|
36221
36430
|
}
|
|
36222
|
-
const { electron: electron$
|
|
36431
|
+
const { electron: electron$t } = window;
|
|
36223
36432
|
function normalisePath(url) {
|
|
36224
36433
|
let path = url.replace(/^\{\{[^}]+\}\}/, "").replace(/^https?:\/\/[^/]+/, "");
|
|
36225
36434
|
if (!path.startsWith("/")) path = "/" + path;
|
|
@@ -36306,7 +36515,7 @@ function SchemaSyncModal({
|
|
|
36306
36515
|
setLoading(true);
|
|
36307
36516
|
setError(null);
|
|
36308
36517
|
try {
|
|
36309
|
-
const entries = await electron$
|
|
36518
|
+
const entries = await electron$t.extractOpenApiSchemas();
|
|
36310
36519
|
if (!entries) {
|
|
36311
36520
|
setLoading(false);
|
|
36312
36521
|
return;
|
|
@@ -36325,7 +36534,7 @@ function SchemaSyncModal({
|
|
|
36325
36534
|
setLoading(true);
|
|
36326
36535
|
setError(null);
|
|
36327
36536
|
try {
|
|
36328
|
-
const entries = await electron$
|
|
36537
|
+
const entries = await electron$t.extractOpenApiSchemasFromUrl(trimmed);
|
|
36329
36538
|
setSpecEntries(entries);
|
|
36330
36539
|
autoSelectChanged(entries);
|
|
36331
36540
|
} catch (err) {
|
|
@@ -36358,7 +36567,7 @@ function SchemaSyncModal({
|
|
|
36358
36567
|
}
|
|
36359
36568
|
const entry = useStore.getState().collections[collectionId];
|
|
36360
36569
|
if (entry) {
|
|
36361
|
-
await electron$
|
|
36570
|
+
await electron$t.saveCollection(entry.relPath, entry.data);
|
|
36362
36571
|
markCollectionClean(collectionId);
|
|
36363
36572
|
}
|
|
36364
36573
|
onClose();
|
|
@@ -36435,7 +36644,7 @@ function SchemaSyncModal({
|
|
|
36435
36644
|
className: "accent-blue-500"
|
|
36436
36645
|
}
|
|
36437
36646
|
),
|
|
36438
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-mono font-bold w-14 shrink-0 ${methodColor$
|
|
36647
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[10px] font-mono font-bold w-14 shrink-0 ${methodColor$3(m.specEntry.method)}`, children: m.specEntry.method }),
|
|
36439
36648
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
36440
36649
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-surface-200 truncate", children: m.request.name }),
|
|
36441
36650
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] text-surface-500 font-mono truncate", children: m.specEntry.pathTemplate })
|
|
@@ -36548,7 +36757,7 @@ function SchemaSyncModal({
|
|
|
36548
36757
|
}
|
|
36549
36758
|
);
|
|
36550
36759
|
}
|
|
36551
|
-
function methodColor$
|
|
36760
|
+
function methodColor$3(method) {
|
|
36552
36761
|
switch (method) {
|
|
36553
36762
|
case "GET":
|
|
36554
36763
|
return "text-emerald-400";
|
|
@@ -36564,6 +36773,284 @@ function methodColor$2(method) {
|
|
|
36564
36773
|
return "text-surface-300";
|
|
36565
36774
|
}
|
|
36566
36775
|
}
|
|
36776
|
+
function folderChainTo(root2, targetId) {
|
|
36777
|
+
if (root2.id === targetId) return [root2];
|
|
36778
|
+
for (const sub of root2.folders) {
|
|
36779
|
+
const chain = folderChainTo(sub, targetId);
|
|
36780
|
+
if (chain.length > 0) return [root2, ...chain];
|
|
36781
|
+
}
|
|
36782
|
+
return [];
|
|
36783
|
+
}
|
|
36784
|
+
function makeHook(req, collectionVars, hookType, scopeId, scopeAncestors, scopePath, mainRequestId) {
|
|
36785
|
+
return { request: req, collectionVars, isHook: true, hookType, scopeId, scopeAncestors, scopePath, mainRequestId };
|
|
36786
|
+
}
|
|
36787
|
+
function buildFolderPlan(folder, requests, collectionVars, filterTags, scopeId, ancestorIds, parentPath, wrappers, isRoot) {
|
|
36788
|
+
const result = [];
|
|
36789
|
+
const scopePath = isRoot ? [] : [...parentPath, folder.name];
|
|
36790
|
+
const folderReqs = folder.requestIds.map((id2) => requests[id2]).filter((r) => r && !r.disabled);
|
|
36791
|
+
const beforeAllHooks = folderReqs.filter((r) => r.hookType === "beforeAll");
|
|
36792
|
+
const beforeHooks = folderReqs.filter((r) => r.hookType === "before");
|
|
36793
|
+
const afterHooks = folderReqs.filter((r) => r.hookType === "after");
|
|
36794
|
+
const afterAllHooks = folderReqs.filter((r) => r.hookType === "afterAll");
|
|
36795
|
+
const regularReqs = folderReqs.filter((r) => !r.hookType);
|
|
36796
|
+
const myWrapper = { scopeId, ancestors: ancestorIds, scopePath, before: beforeHooks, after: afterHooks };
|
|
36797
|
+
const allWrappers = [...wrappers, myWrapper];
|
|
36798
|
+
for (const req of beforeAllHooks) {
|
|
36799
|
+
result.push(makeHook(req, collectionVars, "beforeAll", scopeId, ancestorIds, scopePath));
|
|
36800
|
+
}
|
|
36801
|
+
for (const req of regularReqs) {
|
|
36802
|
+
const tags2 = req.meta?.tags ?? [];
|
|
36803
|
+
if (filterTags.length > 0 && !filterTags.some((t2) => tags2.includes(t2))) continue;
|
|
36804
|
+
for (const w of allWrappers) {
|
|
36805
|
+
for (const hookReq of w.before) {
|
|
36806
|
+
result.push(makeHook(hookReq, collectionVars, "before", w.scopeId, w.ancestors, w.scopePath, req.id));
|
|
36807
|
+
}
|
|
36808
|
+
}
|
|
36809
|
+
result.push({ request: req, collectionVars, scopeId, scopeAncestors: ancestorIds, scopePath });
|
|
36810
|
+
for (const w of [...allWrappers].reverse()) {
|
|
36811
|
+
for (const hookReq of w.after) {
|
|
36812
|
+
result.push(makeHook(hookReq, collectionVars, "after", w.scopeId, w.ancestors, w.scopePath, req.id));
|
|
36813
|
+
}
|
|
36814
|
+
}
|
|
36815
|
+
}
|
|
36816
|
+
for (const sub of folder.folders) {
|
|
36817
|
+
const folderTags = sub.tags ?? [];
|
|
36818
|
+
const effectiveFilter = filterTags.length === 0 ? filterTags : folderTags.some((t2) => filterTags.includes(t2)) ? [] : filterTags;
|
|
36819
|
+
result.push(...buildFolderPlan(
|
|
36820
|
+
sub,
|
|
36821
|
+
requests,
|
|
36822
|
+
collectionVars,
|
|
36823
|
+
effectiveFilter,
|
|
36824
|
+
sub.id,
|
|
36825
|
+
[...ancestorIds, scopeId],
|
|
36826
|
+
scopePath,
|
|
36827
|
+
allWrappers,
|
|
36828
|
+
false
|
|
36829
|
+
));
|
|
36830
|
+
}
|
|
36831
|
+
for (const req of afterAllHooks) {
|
|
36832
|
+
result.push(makeHook(req, collectionVars, "afterAll", scopeId, ancestorIds, scopePath));
|
|
36833
|
+
}
|
|
36834
|
+
return result;
|
|
36835
|
+
}
|
|
36836
|
+
function collectTagged(folder, requests, collectionVars, filterTags, parentPath = [], isRoot = true) {
|
|
36837
|
+
const results = [];
|
|
36838
|
+
const scopePath = isRoot ? parentPath : [...parentPath, folder.name];
|
|
36839
|
+
for (const reqId of folder.requestIds) {
|
|
36840
|
+
const req = requests[reqId];
|
|
36841
|
+
if (!req || req.hookType || req.disabled) continue;
|
|
36842
|
+
const tags2 = req.meta?.tags ?? [];
|
|
36843
|
+
if (filterTags.length > 0 && !filterTags.some((t2) => tags2.includes(t2))) continue;
|
|
36844
|
+
results.push({ request: req, collectionVars, scopePath });
|
|
36845
|
+
}
|
|
36846
|
+
for (const sub of folder.folders) {
|
|
36847
|
+
const folderTags = sub.tags ?? [];
|
|
36848
|
+
const effectiveTags = filterTags.length === 0 ? filterTags : folderTags.some((t2) => filterTags.includes(t2)) ? [] : filterTags;
|
|
36849
|
+
results.push(...collectTagged(sub, requests, collectionVars, effectiveTags, scopePath, false));
|
|
36850
|
+
}
|
|
36851
|
+
return results;
|
|
36852
|
+
}
|
|
36853
|
+
function collectAllTags(folder, requests) {
|
|
36854
|
+
const tags2 = /* @__PURE__ */ new Set();
|
|
36855
|
+
function walk(f) {
|
|
36856
|
+
(f.tags ?? []).forEach((t2) => tags2.add(t2));
|
|
36857
|
+
for (const reqId of f.requestIds) {
|
|
36858
|
+
(requests[reqId]?.meta?.tags ?? []).forEach((t2) => tags2.add(t2));
|
|
36859
|
+
}
|
|
36860
|
+
f.folders.forEach(walk);
|
|
36861
|
+
}
|
|
36862
|
+
walk(folder);
|
|
36863
|
+
return Array.from(tags2).sort();
|
|
36864
|
+
}
|
|
36865
|
+
function folderPathTo(root2, requestId) {
|
|
36866
|
+
if (root2.requestIds.includes(requestId)) return [root2];
|
|
36867
|
+
for (const sub of root2.folders) {
|
|
36868
|
+
const path = folderPathTo(sub, requestId);
|
|
36869
|
+
if (path.length > 0) return [root2, ...path];
|
|
36870
|
+
}
|
|
36871
|
+
return [];
|
|
36872
|
+
}
|
|
36873
|
+
function getHooksForRequest(requestId, collection) {
|
|
36874
|
+
const path = folderPathTo(collection.rootFolder, requestId);
|
|
36875
|
+
const before = [];
|
|
36876
|
+
const afterReversed = [];
|
|
36877
|
+
for (const folder of path) {
|
|
36878
|
+
const reqs = folder.requestIds.map((id2) => collection.requests[id2]).filter((r) => r && !r.disabled);
|
|
36879
|
+
const bAll = reqs.filter((r) => r.hookType === "beforeAll");
|
|
36880
|
+
const bEach = reqs.filter((r) => r.hookType === "before");
|
|
36881
|
+
const aEach = reqs.filter((r) => r.hookType === "after");
|
|
36882
|
+
const aAll = reqs.filter((r) => r.hookType === "afterAll");
|
|
36883
|
+
before.push(...bAll, ...bEach);
|
|
36884
|
+
afterReversed.push(...aEach, ...aAll);
|
|
36885
|
+
}
|
|
36886
|
+
return { before, after: afterReversed.reverse() };
|
|
36887
|
+
}
|
|
36888
|
+
function authIsConfigured(auth) {
|
|
36889
|
+
if (!auth || auth.type === "none") return false;
|
|
36890
|
+
const set2 = (s) => !!(s && s.trim());
|
|
36891
|
+
switch (auth.type) {
|
|
36892
|
+
case "bearer":
|
|
36893
|
+
return set2(auth.token) || set2(auth.tokenSecretRef);
|
|
36894
|
+
case "basic":
|
|
36895
|
+
case "digest":
|
|
36896
|
+
return set2(auth.username) || set2(auth.password) || set2(auth.passwordSecretRef);
|
|
36897
|
+
case "ntlm":
|
|
36898
|
+
return set2(auth.username) || set2(auth.password) || set2(auth.passwordSecretRef);
|
|
36899
|
+
case "apikey":
|
|
36900
|
+
return set2(auth.apiKeyValue) || set2(auth.apiKeySecretRef);
|
|
36901
|
+
case "oauth2":
|
|
36902
|
+
return set2(auth.oauth2TokenUrl) || set2(auth.oauth2ClientId) || set2(auth.oauth2CachedToken);
|
|
36903
|
+
default:
|
|
36904
|
+
return true;
|
|
36905
|
+
}
|
|
36906
|
+
}
|
|
36907
|
+
function resolveInheritedAuthAndHeaders(requestId, collection) {
|
|
36908
|
+
let inheritedAuth = collection.auth && collection.auth.type !== "none" ? collection.auth : null;
|
|
36909
|
+
let inheritedHeaders = collection.headers?.filter((h) => h.enabled && h.key) ?? [];
|
|
36910
|
+
const path = folderPathTo(collection.rootFolder, requestId);
|
|
36911
|
+
for (const folder of path) {
|
|
36912
|
+
if (folder.auth && folder.auth.type !== "none") inheritedAuth = folder.auth;
|
|
36913
|
+
if (folder.headers?.length) {
|
|
36914
|
+
inheritedHeaders = [...inheritedHeaders, ...folder.headers.filter((h) => h.enabled && h.key)];
|
|
36915
|
+
}
|
|
36916
|
+
}
|
|
36917
|
+
return { auth: inheritedAuth, headers: inheritedHeaders };
|
|
36918
|
+
}
|
|
36919
|
+
function buildRunPlan(collection, folderId, filterTags) {
|
|
36920
|
+
const collectionVars = collection.collectionVariables ?? {};
|
|
36921
|
+
if (!folderId) {
|
|
36922
|
+
return buildFolderPlan(
|
|
36923
|
+
collection.rootFolder,
|
|
36924
|
+
collection.requests,
|
|
36925
|
+
collectionVars,
|
|
36926
|
+
filterTags,
|
|
36927
|
+
collection.rootFolder.id,
|
|
36928
|
+
[],
|
|
36929
|
+
[],
|
|
36930
|
+
[],
|
|
36931
|
+
true
|
|
36932
|
+
);
|
|
36933
|
+
}
|
|
36934
|
+
const chain = folderChainTo(collection.rootFolder, folderId);
|
|
36935
|
+
if (chain.length === 0) return [];
|
|
36936
|
+
const targetFolder = chain[chain.length - 1];
|
|
36937
|
+
const ancestors = chain.slice(0, -1);
|
|
36938
|
+
const result = [];
|
|
36939
|
+
const ancestorWrappers = [];
|
|
36940
|
+
const ancestorIds = [];
|
|
36941
|
+
for (const f of ancestors) {
|
|
36942
|
+
const reqs = f.requestIds.map((id2) => collection.requests[id2]).filter((r) => r && !r.disabled);
|
|
36943
|
+
const beforeAllH = reqs.filter((r) => r.hookType === "beforeAll");
|
|
36944
|
+
const beforeH = reqs.filter((r) => r.hookType === "before");
|
|
36945
|
+
const afterH = reqs.filter((r) => r.hookType === "after");
|
|
36946
|
+
for (const req of beforeAllH) {
|
|
36947
|
+
result.push(makeHook(req, collectionVars, "beforeAll", f.id, [...ancestorIds], []));
|
|
36948
|
+
}
|
|
36949
|
+
ancestorWrappers.push({
|
|
36950
|
+
scopeId: f.id,
|
|
36951
|
+
ancestors: [...ancestorIds],
|
|
36952
|
+
scopePath: [],
|
|
36953
|
+
// ancestor hooks render with no folder heading
|
|
36954
|
+
before: beforeH,
|
|
36955
|
+
after: afterH
|
|
36956
|
+
});
|
|
36957
|
+
ancestorIds.push(f.id);
|
|
36958
|
+
}
|
|
36959
|
+
result.push(...buildFolderPlan(
|
|
36960
|
+
targetFolder,
|
|
36961
|
+
collection.requests,
|
|
36962
|
+
collectionVars,
|
|
36963
|
+
filterTags,
|
|
36964
|
+
targetFolder.id,
|
|
36965
|
+
ancestorIds,
|
|
36966
|
+
[],
|
|
36967
|
+
ancestorWrappers,
|
|
36968
|
+
true
|
|
36969
|
+
));
|
|
36970
|
+
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
36971
|
+
const f = ancestors[i];
|
|
36972
|
+
const reqs = f.requestIds.map((id2) => collection.requests[id2]).filter((r) => r && !r.disabled);
|
|
36973
|
+
const afterAllH = reqs.filter((r) => r.hookType === "afterAll");
|
|
36974
|
+
const myAncestors = ancestorIds.slice(0, i);
|
|
36975
|
+
for (const req of afterAllH) {
|
|
36976
|
+
result.push(makeHook(req, collectionVars, "afterAll", f.id, myAncestors, []));
|
|
36977
|
+
}
|
|
36978
|
+
}
|
|
36979
|
+
return result;
|
|
36980
|
+
}
|
|
36981
|
+
function hasContract(r) {
|
|
36982
|
+
const c = r.contract;
|
|
36983
|
+
return !!c && (c.statusCode != null || !!c.bodySchema || !!c.bodyMatcher || (c.headers?.length ?? 0) > 0 || (c.providerStates?.length ?? 0) > 0);
|
|
36984
|
+
}
|
|
36985
|
+
const { electron: electron$s } = window;
|
|
36986
|
+
function cloudEnabled() {
|
|
36987
|
+
return Boolean(useStore.getState().workspace?.settings?.cloud?.enabled);
|
|
36988
|
+
}
|
|
36989
|
+
function assertEnabled() {
|
|
36990
|
+
if (!cloudEnabled()) throw new Error("Cloud is off. Enable it in Settings → Cloud.");
|
|
36991
|
+
}
|
|
36992
|
+
async function pushContractToCloud(requests, opts) {
|
|
36993
|
+
assertEnabled();
|
|
36994
|
+
return electron$s.cloudPushPact({
|
|
36995
|
+
consumer: opts.consumer,
|
|
36996
|
+
provider: opts.provider,
|
|
36997
|
+
consumerVersion: opts.version,
|
|
36998
|
+
requests
|
|
36999
|
+
});
|
|
37000
|
+
}
|
|
37001
|
+
async function pushProviderSpecToCloud(opts) {
|
|
37002
|
+
assertEnabled();
|
|
37003
|
+
return electron$s.cloudPushSpec(opts);
|
|
37004
|
+
}
|
|
37005
|
+
function openCloudMatrix() {
|
|
37006
|
+
void electron$s.cloudOpenMatrix();
|
|
37007
|
+
}
|
|
37008
|
+
async function getCloudMockRoutes(name2) {
|
|
37009
|
+
if (!cloudEnabled()) return null;
|
|
37010
|
+
try {
|
|
37011
|
+
const res = await electron$s.cloudGetMock(name2);
|
|
37012
|
+
return res.exists ? res.routes ?? [] : null;
|
|
37013
|
+
} catch {
|
|
37014
|
+
return null;
|
|
37015
|
+
}
|
|
37016
|
+
}
|
|
37017
|
+
async function pushMockToCloud(server, routeIds) {
|
|
37018
|
+
assertEnabled();
|
|
37019
|
+
const routes = routeIds ? (server.routes ?? []).filter((r) => routeIds.includes(r.id)) : server.routes ?? [];
|
|
37020
|
+
return electron$s.cloudPushMock({ ...server, routes });
|
|
37021
|
+
}
|
|
37022
|
+
async function pushRequestAsMonitor(request, opts) {
|
|
37023
|
+
assertEnabled();
|
|
37024
|
+
const s = useStore.getState();
|
|
37025
|
+
const colEntry = Object.values(s.collections).find((c) => c.data.requests[request.id]);
|
|
37026
|
+
const collectionVars = {
|
|
37027
|
+
...colEntry?.data.collectionVariables ?? {},
|
|
37028
|
+
...s.getInheritedVariables(request.id),
|
|
37029
|
+
...s.sessionVars
|
|
37030
|
+
};
|
|
37031
|
+
const setup = colEntry ? getHooksForRequest(request.id, colEntry.data).before : [];
|
|
37032
|
+
const environment = resolveEnvironmentById(s.environments, s.activeEnvironmentId);
|
|
37033
|
+
const globals = { ...s.globals };
|
|
37034
|
+
const inherited = s.getInheritedAuthAndHeaders(request.id);
|
|
37035
|
+
const mergedAuth = authIsConfigured(request.auth) ? request.auth : inherited.auth ?? request.auth;
|
|
37036
|
+
const mergedHeaders = [
|
|
37037
|
+
...inherited.headers.filter((h) => h.enabled),
|
|
37038
|
+
...request.headers
|
|
37039
|
+
];
|
|
37040
|
+
const mergedRequest = { ...request, auth: mergedAuth, headers: mergedHeaders };
|
|
37041
|
+
return electron$s.cloudPushMonitor(
|
|
37042
|
+
{
|
|
37043
|
+
request: mergedRequest,
|
|
37044
|
+
setup,
|
|
37045
|
+
environment,
|
|
37046
|
+
collectionVars,
|
|
37047
|
+
globals,
|
|
37048
|
+
name: request.name,
|
|
37049
|
+
intervalSeconds: opts?.intervalSeconds,
|
|
37050
|
+
expectedStatus: opts?.expectedStatus
|
|
37051
|
+
}
|
|
37052
|
+
);
|
|
37053
|
+
}
|
|
36567
37054
|
const METHOD_COLORS$1 = {
|
|
36568
37055
|
GET: "text-emerald-400",
|
|
36569
37056
|
POST: "text-blue-400",
|
|
@@ -36587,6 +37074,143 @@ const STATUS_COLORS = {
|
|
|
36587
37074
|
function getStatusColor(status) {
|
|
36588
37075
|
return STATUS_COLORS[String(status)[0]] ?? "text-gray-400";
|
|
36589
37076
|
}
|
|
37077
|
+
function PushContractModal({ requests, defaultConsumer, onClose }) {
|
|
37078
|
+
const snapshots = useStore((s) => s.contractSnapshots);
|
|
37079
|
+
const snapshotEntries = Object.entries(snapshots);
|
|
37080
|
+
const withContract = requests.filter(hasContract);
|
|
37081
|
+
const [mode, setMode] = reactExports.useState("consumer");
|
|
37082
|
+
const [consumer, setConsumer] = reactExports.useState(defaultConsumer);
|
|
37083
|
+
const [provider, setProvider] = reactExports.useState("");
|
|
37084
|
+
const [version, setVersion] = reactExports.useState("");
|
|
37085
|
+
const [selected, setSelected] = reactExports.useState(new Set(withContract.map((r) => r.id)));
|
|
37086
|
+
const [pacticipant, setPacticipant] = reactExports.useState("");
|
|
37087
|
+
const [snapshotPath, setSnapshotPath] = reactExports.useState(snapshotEntries[0]?.[0] ?? "");
|
|
37088
|
+
const [status, setStatus] = reactExports.useState({ state: "idle" });
|
|
37089
|
+
function toggle(id2) {
|
|
37090
|
+
setSelected((prev) => {
|
|
37091
|
+
const n = new Set(prev);
|
|
37092
|
+
if (n.has(id2)) n.delete(id2);
|
|
37093
|
+
else n.add(id2);
|
|
37094
|
+
return n;
|
|
37095
|
+
});
|
|
37096
|
+
}
|
|
37097
|
+
const canPush = mode === "consumer" ? Boolean(consumer.trim() && provider.trim() && version.trim() && selected.size) : Boolean(pacticipant.trim() && version.trim() && snapshotPath);
|
|
37098
|
+
async function push2() {
|
|
37099
|
+
setStatus({ state: "pushing" });
|
|
37100
|
+
try {
|
|
37101
|
+
if (mode === "consumer") {
|
|
37102
|
+
const chosen = withContract.filter((r2) => selected.has(r2.id));
|
|
37103
|
+
const r = await pushContractToCloud(chosen, { consumer: consumer.trim(), provider: provider.trim(), version: version.trim() });
|
|
37104
|
+
const published = `Published ${consumer} → ${provider} (${chosen.length} interactions).`;
|
|
37105
|
+
if (!r.verification) {
|
|
37106
|
+
setStatus({ state: "warn", msg: `${published} Not verified yet: ${provider} has not published its OpenAPI spec.` });
|
|
37107
|
+
} else if (r.verification.success) {
|
|
37108
|
+
setStatus({ state: "ok", msg: `${published} Compatible with ${provider}. ✓` });
|
|
37109
|
+
} else {
|
|
37110
|
+
const failing = r.verification.checks.filter((c) => !c.passed);
|
|
37111
|
+
setStatus({ state: "err", msg: `${published} NOT compatible with ${provider} (${failing.length} failing).`, detail: failing.map((c) => `${c.interaction}: ${c.error}`) });
|
|
37112
|
+
}
|
|
37113
|
+
} else {
|
|
37114
|
+
const spec = snapshots[snapshotPath]?.spec ?? "";
|
|
37115
|
+
const r = await pushProviderSpecToCloud({ pacticipant: pacticipant.trim(), version: version.trim(), spec });
|
|
37116
|
+
const failing = r.results.filter((x) => !x.success);
|
|
37117
|
+
if (r.results.length === 0) {
|
|
37118
|
+
setStatus({ state: "warn", msg: `Published ${pacticipant} spec. No consumer contracts to verify yet.` });
|
|
37119
|
+
} else if (failing.length === 0) {
|
|
37120
|
+
setStatus({ state: "ok", msg: `Published ${pacticipant} spec. All ${r.results.length} consumer contract(s) compatible. ✓` });
|
|
37121
|
+
} else {
|
|
37122
|
+
setStatus({ state: "err", msg: `Published ${pacticipant} spec. ${failing.length} of ${r.results.length} consumer(s) now incompatible.`, detail: failing.map((x) => `${x.consumer} ${x.version}`) });
|
|
37123
|
+
}
|
|
37124
|
+
}
|
|
37125
|
+
} catch (e) {
|
|
37126
|
+
setStatus({ state: "err", msg: e.message });
|
|
37127
|
+
}
|
|
37128
|
+
}
|
|
37129
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
37130
|
+
Modal,
|
|
37131
|
+
{
|
|
37132
|
+
onClose,
|
|
37133
|
+
overlayClassName: "bg-black/50 z-50 flex items-start justify-center pt-24",
|
|
37134
|
+
panelClassName: "bg-surface-900 border border-surface-800 rounded-lg shadow-2xl w-[520px] flex flex-col max-h-[75vh]",
|
|
37135
|
+
title: "Push contract to cloud",
|
|
37136
|
+
children: [
|
|
37137
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-1 px-4 pt-3 flex-shrink-0", children: ["consumer", "provider"].map((m) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37138
|
+
"button",
|
|
37139
|
+
{
|
|
37140
|
+
onClick: () => setMode(m),
|
|
37141
|
+
disabled: m === "provider" && snapshotEntries.length === 0,
|
|
37142
|
+
className: `px-3 py-1.5 text-xs rounded transition-colors disabled:opacity-30 ${mode === m ? "bg-blue-600 text-white" : "bg-surface-800 hover:bg-surface-700 text-surface-300"}`,
|
|
37143
|
+
children: m === "consumer" ? "Consumer pact" : "Provider spec (OpenAPI)"
|
|
37144
|
+
},
|
|
37145
|
+
m
|
|
37146
|
+
)) }),
|
|
37147
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4 flex flex-col gap-3 text-xs", children: mode === "consumer" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
37148
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
|
|
37149
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
37150
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-500", children: "Consumer" }),
|
|
37151
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("input", { value: consumer, onChange: (e) => setConsumer(e.target.value), className: "bg-surface-800 border border-surface-700 rounded px-2.5 py-1.5 focus:outline-none focus:border-blue-500" })
|
|
37152
|
+
] }),
|
|
37153
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
37154
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-500", children: "Provider" }),
|
|
37155
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("input", { value: provider, onChange: (e) => setProvider(e.target.value), placeholder: "orders-api", className: "bg-surface-800 border border-surface-700 rounded px-2.5 py-1.5 focus:outline-none focus:border-blue-500 placeholder-surface-600" })
|
|
37156
|
+
] })
|
|
37157
|
+
] }),
|
|
37158
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
37159
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-500", children: [
|
|
37160
|
+
"Version ",
|
|
37161
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600", children: "(git sha / build)" })
|
|
37162
|
+
] }),
|
|
37163
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("input", { value: version, onChange: (e) => setVersion(e.target.value), placeholder: "1.4.0", className: "bg-surface-800 border border-surface-700 rounded px-2.5 py-1.5 focus:outline-none focus:border-blue-500 placeholder-surface-600" })
|
|
37164
|
+
] }),
|
|
37165
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
37166
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-surface-500 mb-1.5", children: [
|
|
37167
|
+
"Interactions ",
|
|
37168
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600", children: "(requests with a contract)" })
|
|
37169
|
+
] }),
|
|
37170
|
+
withContract.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-surface-500 px-1 py-3", children: "No requests here have a contract yet. Add expected status/schema on a request's Contract tab first." }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-lg border border-surface-800 max-h-56 overflow-y-auto", children: withContract.map((r) => /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-center gap-2 px-2 py-1.5 hover:bg-surface-800/50 cursor-pointer", children: [
|
|
37171
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "checkbox", checked: selected.has(r.id), onChange: () => toggle(r.id), className: "accent-blue-500" }),
|
|
37172
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-semibold w-12 flex-shrink-0", style: { color: getMethodColor(r.method) }, children: r.method }),
|
|
37173
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-300 truncate", children: r.name }),
|
|
37174
|
+
r.contract?.statusCode && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-auto text-surface-500 flex-shrink-0", children: r.contract.statusCode })
|
|
37175
|
+
] }, r.id)) })
|
|
37176
|
+
] })
|
|
37177
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
37178
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-surface-500", children: "Publishes a pinned OpenAPI spec as the provider contract. Consumer pacts are then verified against it without running the provider." }),
|
|
37179
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
|
|
37180
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
37181
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-500", children: "Provider (pacticipant)" }),
|
|
37182
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("input", { value: pacticipant, onChange: (e) => setPacticipant(e.target.value), placeholder: "orders-api", className: "bg-surface-800 border border-surface-700 rounded px-2.5 py-1.5 focus:outline-none focus:border-blue-500 placeholder-surface-600" })
|
|
37183
|
+
] }),
|
|
37184
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
37185
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-500", children: "Version" }),
|
|
37186
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("input", { value: version, onChange: (e) => setVersion(e.target.value), placeholder: "2.1.0", className: "bg-surface-800 border border-surface-700 rounded px-2.5 py-1.5 focus:outline-none focus:border-blue-500 placeholder-surface-600" })
|
|
37187
|
+
] })
|
|
37188
|
+
] }),
|
|
37189
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
37190
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-500", children: "Spec snapshot" }),
|
|
37191
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("select", { value: snapshotPath, onChange: (e) => setSnapshotPath(e.target.value), className: "bg-surface-800 border border-surface-700 rounded px-2.5 py-1.5 focus:outline-none focus:border-blue-500", children: snapshotEntries.map(([path, snap]) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: path, children: snap.name ?? path }, path)) })
|
|
37192
|
+
] })
|
|
37193
|
+
] }) }),
|
|
37194
|
+
(status.state === "ok" || status.state === "warn" || status.state === "err") && status.detail?.length ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-4 mb-2 px-3 py-2 rounded bg-surface-800/60 border border-surface-700 text-[11px] text-surface-300 max-h-24 overflow-y-auto flex-shrink-0", children: status.detail.map((d, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "font-mono truncate", children: [
|
|
37195
|
+
"• ",
|
|
37196
|
+
d
|
|
37197
|
+
] }, i)) }) : null,
|
|
37198
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-3 border-t border-surface-800 flex items-center gap-2 flex-shrink-0", children: status.state === "ok" || status.state === "warn" || status.state === "err" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
37199
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: `text-[11px] flex-1 ${status.state === "ok" ? "text-green-400" : status.state === "warn" ? "text-amber-400" : "text-red-400"}`, children: [
|
|
37200
|
+
status.state === "ok" ? "✓" : status.state === "warn" ? "⚠" : "✗",
|
|
37201
|
+
" ",
|
|
37202
|
+
status.msg
|
|
37203
|
+
] }),
|
|
37204
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => openCloudMatrix(), className: "px-3 py-1.5 bg-surface-800 hover:bg-surface-700 rounded text-xs", children: "View matrix ↗" }),
|
|
37205
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "px-4 py-1.5 bg-blue-600 hover:bg-blue-500 rounded text-xs font-medium", children: "Done" })
|
|
37206
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
37207
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: push2, disabled: !canPush || status.state === "pushing", className: "ml-auto px-4 py-1.5 bg-blue-600 hover:bg-blue-500 disabled:opacity-40 rounded text-xs font-medium", children: status.state === "pushing" ? "Publishing…" : "Publish" }),
|
|
37208
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "px-4 py-1.5 bg-surface-800 hover:bg-surface-700 rounded text-xs", children: "Cancel" })
|
|
37209
|
+
] }) })
|
|
37210
|
+
]
|
|
37211
|
+
}
|
|
37212
|
+
);
|
|
37213
|
+
}
|
|
36590
37214
|
function MethodBadge({ method, size = "sm" }) {
|
|
36591
37215
|
const color = getMethodColor(method);
|
|
36592
37216
|
const cls = size === "xs" ? "text-[10px] font-bold w-10" : "text-xs font-bold w-12";
|
|
@@ -36759,6 +37383,20 @@ function DotsBtn({ items: items2 }) {
|
|
|
36759
37383
|
menu && /* @__PURE__ */ jsxRuntimeExports.jsx(ContextMenu, { items: items2, x: menu.x, y: menu.y, onClose: () => setMenu(null) })
|
|
36760
37384
|
] });
|
|
36761
37385
|
}
|
|
37386
|
+
function useToast(durationMs = 3e3) {
|
|
37387
|
+
const [toast, setToast] = reactExports.useState(null);
|
|
37388
|
+
const timer = reactExports.useRef(null);
|
|
37389
|
+
function show(msg, ok) {
|
|
37390
|
+
if (timer.current) clearTimeout(timer.current);
|
|
37391
|
+
setToast({ msg, ok });
|
|
37392
|
+
timer.current = setTimeout(() => setToast(null), durationMs);
|
|
37393
|
+
}
|
|
37394
|
+
return { toast, show };
|
|
37395
|
+
}
|
|
37396
|
+
function Toast({ toast }) {
|
|
37397
|
+
if (!toast) return null;
|
|
37398
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `mx-3 mb-2 px-2 py-1.5 rounded text-[11px] flex-shrink-0 ${toast.ok ? "bg-emerald-900/50 text-emerald-300 border border-emerald-800/50" : "bg-red-900/50 text-red-300 border border-red-800/50"}`, children: toast.msg });
|
|
37399
|
+
}
|
|
36762
37400
|
function requestPath(url) {
|
|
36763
37401
|
const trimmed = url.trim().replace(/^\{\{[^}]+\}\}/, "").replace(/^https?:\/\/[^/]+/i, "");
|
|
36764
37402
|
return trimmed || url.trim();
|
|
@@ -36799,19 +37437,49 @@ function RequestRow({
|
|
|
36799
37437
|
isActive,
|
|
36800
37438
|
indent: indent2,
|
|
36801
37439
|
autoRename = false,
|
|
37440
|
+
examples = [],
|
|
37441
|
+
activeExampleId,
|
|
36802
37442
|
onSelect,
|
|
36803
37443
|
onRename,
|
|
36804
37444
|
onDelete,
|
|
36805
37445
|
onDuplicate,
|
|
36806
37446
|
onUpdateTags,
|
|
36807
37447
|
onSetHookType,
|
|
36808
|
-
onToggleDisabled
|
|
37448
|
+
onToggleDisabled,
|
|
37449
|
+
onAddExample,
|
|
37450
|
+
onOpenExample,
|
|
37451
|
+
onRenameExample,
|
|
37452
|
+
onDeleteExample,
|
|
37453
|
+
onDuplicateExample
|
|
36809
37454
|
}) {
|
|
36810
37455
|
const [renaming, setRenaming] = reactExports.useState(autoRename);
|
|
37456
|
+
const [examplesOpen, setExamplesOpen] = reactExports.useState(true);
|
|
36811
37457
|
const [addingTag, setAddingTag] = reactExports.useState(false);
|
|
36812
37458
|
const [showSchemaSync, setShowSchemaSync] = reactExports.useState(false);
|
|
36813
37459
|
const [dropPos, setDropPos] = reactExports.useState(null);
|
|
36814
37460
|
const dragCtx = reactExports.useContext(DragCtx);
|
|
37461
|
+
const sel = reactExports.useContext(SelectionCtx);
|
|
37462
|
+
const selected = sel.isSelected(collectionId, reqId);
|
|
37463
|
+
const { toast, show } = useToast();
|
|
37464
|
+
function handleRowClick(e) {
|
|
37465
|
+
if (e.metaKey || e.ctrlKey) {
|
|
37466
|
+
e.preventDefault();
|
|
37467
|
+
sel.toggle(collectionId, reqId);
|
|
37468
|
+
return;
|
|
37469
|
+
}
|
|
37470
|
+
if (sel.active) sel.clear();
|
|
37471
|
+
onSelect();
|
|
37472
|
+
}
|
|
37473
|
+
async function pushMonitor() {
|
|
37474
|
+
const req = useStore.getState().collections[collectionId]?.data.requests[reqId];
|
|
37475
|
+
if (!req) return;
|
|
37476
|
+
try {
|
|
37477
|
+
const r = await pushRequestAsMonitor(req);
|
|
37478
|
+
show(`Pushed "${req.name}" as monitor #${r.id} to the cloud`, true);
|
|
37479
|
+
} catch (e) {
|
|
37480
|
+
show(e.message, false);
|
|
37481
|
+
}
|
|
37482
|
+
}
|
|
36815
37483
|
const hookMenuItems = ["beforeAll", "before", "after", "afterAll"].map((ht) => ({
|
|
36816
37484
|
type: "item",
|
|
36817
37485
|
label: (hookType === ht ? "✓ " : " ") + HOOK_LABELS[ht],
|
|
@@ -36836,9 +37504,9 @@ function RequestRow({
|
|
|
36836
37504
|
"div",
|
|
36837
37505
|
{
|
|
36838
37506
|
draggable: true,
|
|
36839
|
-
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"}`,
|
|
37507
|
+
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"}`,
|
|
36840
37508
|
style: { paddingLeft: indent2 },
|
|
36841
|
-
onClick:
|
|
37509
|
+
onClick: handleRowClick,
|
|
36842
37510
|
onDoubleClick: () => setRenaming(true),
|
|
36843
37511
|
onDragStart: (e) => {
|
|
36844
37512
|
e.dataTransfer.effectAllowed = "move";
|
|
@@ -36852,6 +37520,29 @@ function RequestRow({
|
|
|
36852
37520
|
onDragLeave: () => setDropPos(null),
|
|
36853
37521
|
onDrop: handleDrop,
|
|
36854
37522
|
children: [
|
|
37523
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37524
|
+
"input",
|
|
37525
|
+
{
|
|
37526
|
+
type: "checkbox",
|
|
37527
|
+
checked: selected,
|
|
37528
|
+
onClick: (e) => e.stopPropagation(),
|
|
37529
|
+
onChange: () => sel.toggle(collectionId, reqId),
|
|
37530
|
+
title: "Select request (or Cmd/Ctrl+click the row)",
|
|
37531
|
+
className: `shrink-0 mt-0.5 accent-blue-500 cursor-pointer ${sel.active || selected ? "" : "opacity-0 group-hover:opacity-100"}`
|
|
37532
|
+
}
|
|
37533
|
+
),
|
|
37534
|
+
examples.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37535
|
+
"button",
|
|
37536
|
+
{
|
|
37537
|
+
onClick: (e) => {
|
|
37538
|
+
e.stopPropagation();
|
|
37539
|
+
setExamplesOpen((o) => !o);
|
|
37540
|
+
},
|
|
37541
|
+
className: "shrink-0 w-3 text-surface-500 hover:text-white leading-none",
|
|
37542
|
+
title: examplesOpen ? "Hide examples" : `Show ${examples.length} example(s)`,
|
|
37543
|
+
children: examplesOpen ? "▾" : "▸"
|
|
37544
|
+
}
|
|
37545
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 w-3" }),
|
|
36855
37546
|
protocol === "soap" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
36856
37547
|
"span",
|
|
36857
37548
|
{
|
|
@@ -36909,19 +37600,38 @@ function RequestRow({
|
|
|
36909
37600
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DotsBtn, { items: [
|
|
36910
37601
|
{ type: "item", label: "Rename", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(PencilIcon, {}), onClick: () => setRenaming(true) },
|
|
36911
37602
|
{ type: "item", label: "Duplicate", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: onDuplicate },
|
|
37603
|
+
...onAddExample ? [{ type: "item", label: "Add Example", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: () => {
|
|
37604
|
+
onAddExample();
|
|
37605
|
+
setExamplesOpen(true);
|
|
37606
|
+
} }] : [],
|
|
36912
37607
|
{ type: "item", label: "Add tag", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TagIcon, {}), onClick: () => setAddingTag(true) },
|
|
36913
37608
|
{ type: "item", label: "Sync schema", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowSchemaSync(true) },
|
|
36914
37609
|
{ type: "item", label: disabled ? "Enable" : "Disable", onClick: onToggleDisabled },
|
|
37610
|
+
...cloudEnabled() ? [{ type: "item", label: "Push as monitor to cloud", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: pushMonitor }] : [],
|
|
36915
37611
|
{ type: "separator" },
|
|
36916
37612
|
{ type: "header", label: "Hook type" },
|
|
36917
37613
|
...hookMenuItems,
|
|
36918
37614
|
{ type: "separator" },
|
|
36919
37615
|
{ type: "item", label: "Delete", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TrashIcon, {}), danger: true, onClick: onDelete }
|
|
36920
37616
|
] }) }),
|
|
37617
|
+
toast && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed bottom-4 right-4 z-[100] w-96", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Toast, { toast }) }),
|
|
36921
37618
|
dropPos === "after" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute bottom-0 inset-x-0 h-0.5 bg-blue-500 z-10 pointer-events-none" })
|
|
36922
37619
|
]
|
|
36923
37620
|
}
|
|
36924
37621
|
),
|
|
37622
|
+
examplesOpen && examples.map((ex) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37623
|
+
ExampleRow,
|
|
37624
|
+
{
|
|
37625
|
+
name: ex.name,
|
|
37626
|
+
indent: indent2 + 18,
|
|
37627
|
+
isActive: activeExampleId === ex.id,
|
|
37628
|
+
onOpen: () => onOpenExample?.(ex.id),
|
|
37629
|
+
onRename: (n) => onRenameExample?.(ex.id, n),
|
|
37630
|
+
onDelete: () => onDeleteExample?.(ex.id),
|
|
37631
|
+
onDuplicate: () => onDuplicateExample?.(ex.id)
|
|
37632
|
+
},
|
|
37633
|
+
ex.id
|
|
37634
|
+
)),
|
|
36925
37635
|
showSchemaSync && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
36926
37636
|
SchemaSyncModal,
|
|
36927
37637
|
{
|
|
@@ -36932,6 +37642,40 @@ function RequestRow({
|
|
|
36932
37642
|
)
|
|
36933
37643
|
] });
|
|
36934
37644
|
}
|
|
37645
|
+
function ExampleRow({ name: name2, indent: indent2, isActive, onOpen, onRename, onDelete, onDuplicate }) {
|
|
37646
|
+
const [renaming, setRenaming] = reactExports.useState(false);
|
|
37647
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
37648
|
+
"div",
|
|
37649
|
+
{
|
|
37650
|
+
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"}`,
|
|
37651
|
+
style: { paddingLeft: indent2 },
|
|
37652
|
+
onClick: onOpen,
|
|
37653
|
+
onDoubleClick: () => setRenaming(true),
|
|
37654
|
+
children: [
|
|
37655
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 text-[8px] font-bold px-1 py-px rounded bg-surface-700 text-surface-300", title: "Example", children: "EX" }),
|
|
37656
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-w-0", children: renaming ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37657
|
+
InlineEdit,
|
|
37658
|
+
{
|
|
37659
|
+
value: name2,
|
|
37660
|
+
onCommit: (v) => {
|
|
37661
|
+
onRename(v);
|
|
37662
|
+
setRenaming(false);
|
|
37663
|
+
},
|
|
37664
|
+
onCancel: () => setRenaming(false),
|
|
37665
|
+
className: "w-full text-xs"
|
|
37666
|
+
}
|
|
37667
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs truncate", children: name2 }) }),
|
|
37668
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DotsBtn, { items: [
|
|
37669
|
+
{ type: "item", label: "Open", onClick: onOpen },
|
|
37670
|
+
{ type: "item", label: "Rename", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(PencilIcon, {}), onClick: () => setRenaming(true) },
|
|
37671
|
+
{ type: "item", label: "Duplicate", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: onDuplicate },
|
|
37672
|
+
{ type: "separator" },
|
|
37673
|
+
{ type: "item", label: "Delete", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TrashIcon, {}), danger: true, onClick: onDelete }
|
|
37674
|
+
] }) })
|
|
37675
|
+
]
|
|
37676
|
+
}
|
|
37677
|
+
);
|
|
37678
|
+
}
|
|
36935
37679
|
function ConfirmDialog({ message, onConfirm, onCancel }) {
|
|
36936
37680
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
36937
37681
|
Modal,
|
|
@@ -36967,6 +37711,9 @@ const DragCtx = reactExports.createContext({ dragging: null, setDragging: () =>
|
|
|
36967
37711
|
}, onDropRequest: () => {
|
|
36968
37712
|
}, onDropFolder: () => {
|
|
36969
37713
|
} });
|
|
37714
|
+
const SelectionCtx = reactExports.createContext({ active: false, isSelected: () => false, toggle: () => {
|
|
37715
|
+
}, clear: () => {
|
|
37716
|
+
} });
|
|
36970
37717
|
function TagChips({
|
|
36971
37718
|
tags: tags2,
|
|
36972
37719
|
onRemove,
|
|
@@ -37031,6 +37778,36 @@ function TagChips({
|
|
|
37031
37778
|
) : null
|
|
37032
37779
|
] });
|
|
37033
37780
|
}
|
|
37781
|
+
function methodColor$2(method) {
|
|
37782
|
+
switch (method) {
|
|
37783
|
+
case "GET":
|
|
37784
|
+
return "text-emerald-400";
|
|
37785
|
+
case "POST":
|
|
37786
|
+
return "text-amber-400";
|
|
37787
|
+
case "PUT":
|
|
37788
|
+
return "text-sky-400";
|
|
37789
|
+
case "PATCH":
|
|
37790
|
+
return "text-violet-400";
|
|
37791
|
+
case "DELETE":
|
|
37792
|
+
return "text-red-400";
|
|
37793
|
+
default:
|
|
37794
|
+
return "text-surface-300";
|
|
37795
|
+
}
|
|
37796
|
+
}
|
|
37797
|
+
function collectMatches(col, q) {
|
|
37798
|
+
const out = [];
|
|
37799
|
+
const walk = (folder, path) => {
|
|
37800
|
+
for (const reqId of folder.requestIds) {
|
|
37801
|
+
const req = col.requests[reqId];
|
|
37802
|
+
if (!req) continue;
|
|
37803
|
+
const hay = [req.name, req.url, req.method, ...req.meta?.tags ?? []].join(" ").toLowerCase();
|
|
37804
|
+
if (hay.includes(q)) out.push({ collectionId: col.id, collectionName: col.name, req, path });
|
|
37805
|
+
}
|
|
37806
|
+
for (const sub of folder.folders) walk(sub, [...path, sub.name]);
|
|
37807
|
+
};
|
|
37808
|
+
walk(col.rootFolder, []);
|
|
37809
|
+
return out;
|
|
37810
|
+
}
|
|
37034
37811
|
function CollectionTree() {
|
|
37035
37812
|
const collections = useStore((s) => s.collections);
|
|
37036
37813
|
const activeCollectionId = useStore((s) => s.activeCollectionId);
|
|
@@ -37059,7 +37836,30 @@ function CollectionTree() {
|
|
|
37059
37836
|
const moveRequest = useStore((s) => s.moveRequest);
|
|
37060
37837
|
const moveFolder = useStore((s) => s.moveFolder);
|
|
37061
37838
|
const colList = Object.values(collections);
|
|
37839
|
+
const [query, setQuery] = reactExports.useState("");
|
|
37840
|
+
const q = query.trim().toLowerCase();
|
|
37841
|
+
const matches = q ? colList.flatMap(({ data }) => collectMatches(data, q)) : [];
|
|
37062
37842
|
const [pendingConfirm, setPendingConfirm] = reactExports.useState(null);
|
|
37843
|
+
const [selected, setSelected] = reactExports.useState(() => /* @__PURE__ */ new Set());
|
|
37844
|
+
const selKey = (c, r) => `${c}\0${r}`;
|
|
37845
|
+
const selectionCtx = {
|
|
37846
|
+
active: selected.size > 0,
|
|
37847
|
+
isSelected: (c, r) => selected.has(selKey(c, r)),
|
|
37848
|
+
toggle: (c, r) => setSelected((prev) => {
|
|
37849
|
+
const next = new Set(prev);
|
|
37850
|
+
const k = selKey(c, r);
|
|
37851
|
+
if (next.has(k)) next.delete(k);
|
|
37852
|
+
else next.add(k);
|
|
37853
|
+
return next;
|
|
37854
|
+
}),
|
|
37855
|
+
clear: () => setSelected(/* @__PURE__ */ new Set())
|
|
37856
|
+
};
|
|
37857
|
+
function forEachSelected(fn) {
|
|
37858
|
+
selected.forEach((k) => {
|
|
37859
|
+
const i = k.indexOf("\0");
|
|
37860
|
+
fn(k.slice(0, i), k.slice(i + 1));
|
|
37861
|
+
});
|
|
37862
|
+
}
|
|
37063
37863
|
const [newRequestId, setNewRequestId] = reactExports.useState(null);
|
|
37064
37864
|
const [dragging, setDragging] = reactExports.useState(null);
|
|
37065
37865
|
function confirmThen(message, action) {
|
|
@@ -37079,7 +37879,7 @@ function CollectionTree() {
|
|
|
37079
37879
|
moveFolder(dragging.collectionId, dragging.folderId, destParentFolderId, destIndex);
|
|
37080
37880
|
setDragging(null);
|
|
37081
37881
|
}
|
|
37082
|
-
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: [
|
|
37882
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(DragCtx.Provider, { value: { dragging, setDragging, onDropRequest, onDropFolder }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectionCtx.Provider, { value: selectionCtx, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col flex-1 min-h-0 select-none", children: [
|
|
37083
37883
|
pendingConfirm && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37084
37884
|
ConfirmDialog,
|
|
37085
37885
|
{
|
|
@@ -37088,7 +37888,55 @@ function CollectionTree() {
|
|
|
37088
37888
|
onCancel: () => setPendingConfirm(null)
|
|
37089
37889
|
}
|
|
37090
37890
|
),
|
|
37091
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
37891
|
+
colList.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-2 py-1.5 border-b border-surface-800 shrink-0", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
|
|
37892
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37893
|
+
"input",
|
|
37894
|
+
{
|
|
37895
|
+
value: query,
|
|
37896
|
+
onChange: (e) => setQuery(e.target.value),
|
|
37897
|
+
onKeyDown: (e) => {
|
|
37898
|
+
if (e.key === "Escape") setQuery("");
|
|
37899
|
+
},
|
|
37900
|
+
placeholder: "Search requests…",
|
|
37901
|
+
className: "w-full text-xs bg-surface-800 border border-surface-700 rounded pl-2 pr-6 py-1 focus:outline-none focus:border-blue-500 placeholder-surface-500"
|
|
37902
|
+
}
|
|
37903
|
+
),
|
|
37904
|
+
query && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37905
|
+
"button",
|
|
37906
|
+
{
|
|
37907
|
+
onClick: () => setQuery(""),
|
|
37908
|
+
title: "Clear (Esc)",
|
|
37909
|
+
className: "absolute right-1 top-1/2 -translate-y-1/2 w-4 h-4 flex items-center justify-center text-surface-500 hover:text-surface-200 leading-none",
|
|
37910
|
+
children: "×"
|
|
37911
|
+
}
|
|
37912
|
+
)
|
|
37913
|
+
] }) }),
|
|
37914
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: q ? matches.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "px-3 py-3 text-xs text-surface-500", children: [
|
|
37915
|
+
"No requests match “",
|
|
37916
|
+
query.trim(),
|
|
37917
|
+
"”."
|
|
37918
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "py-1", children: [
|
|
37919
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "px-3 pb-1 text-[10px] uppercase tracking-wider text-surface-500", children: [
|
|
37920
|
+
matches.length,
|
|
37921
|
+
" ",
|
|
37922
|
+
matches.length === 1 ? "match" : "matches"
|
|
37923
|
+
] }),
|
|
37924
|
+
matches.map(({ collectionId, collectionName, req, path }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
37925
|
+
"button",
|
|
37926
|
+
{
|
|
37927
|
+
onClick: () => openInTab(req.id, collectionId),
|
|
37928
|
+
className: `w-full text-left flex items-baseline gap-2 px-3 py-1 hover:bg-surface-800 transition-colors ${req.id === activeRequestId ? "bg-surface-800" : ""}`,
|
|
37929
|
+
children: [
|
|
37930
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `text-[9px] font-mono font-bold w-10 shrink-0 ${methodColor$2(req.method)}`, children: req.method }),
|
|
37931
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex-1 min-w-0", children: [
|
|
37932
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-surface-200 truncate block", children: req.name }),
|
|
37933
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-surface-500 truncate block", children: [collectionName, ...path].join(" › ") })
|
|
37934
|
+
] })
|
|
37935
|
+
]
|
|
37936
|
+
},
|
|
37937
|
+
`${collectionId}:${req.id}`
|
|
37938
|
+
))
|
|
37939
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
37092
37940
|
colList.map(({ data: col }) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37093
37941
|
CollectionNode,
|
|
37094
37942
|
{
|
|
@@ -37130,8 +37978,66 @@ function CollectionTree() {
|
|
|
37130
37978
|
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => addCollection("New Collection"), className: "text-blue-400 hover:text-blue-300 transition-colors", children: "+ New collection" }),
|
|
37131
37979
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "pt-1", children: "or import from Postman / OpenAPI above." })
|
|
37132
37980
|
] })
|
|
37981
|
+
] }) }),
|
|
37982
|
+
selected.size > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "shrink-0 border-t border-surface-700 bg-surface-900 px-2 py-1.5 flex items-center gap-1 text-xs", children: [
|
|
37983
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-300 mr-auto", children: [
|
|
37984
|
+
selected.size,
|
|
37985
|
+
" selected"
|
|
37986
|
+
] }),
|
|
37987
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37988
|
+
"button",
|
|
37989
|
+
{
|
|
37990
|
+
onClick: () => forEachSelected((_c, r) => updateRequest(r, { disabled: false })),
|
|
37991
|
+
className: "px-2 py-0.5 rounded hover:bg-surface-800 text-surface-300 transition-colors",
|
|
37992
|
+
title: "Enable selected requests",
|
|
37993
|
+
children: "Enable"
|
|
37994
|
+
}
|
|
37995
|
+
),
|
|
37996
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37997
|
+
"button",
|
|
37998
|
+
{
|
|
37999
|
+
onClick: () => forEachSelected((_c, r) => updateRequest(r, { disabled: true })),
|
|
38000
|
+
className: "px-2 py-0.5 rounded hover:bg-surface-800 text-surface-300 transition-colors",
|
|
38001
|
+
title: "Disable selected requests",
|
|
38002
|
+
children: "Disable"
|
|
38003
|
+
}
|
|
38004
|
+
),
|
|
38005
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
38006
|
+
"button",
|
|
38007
|
+
{
|
|
38008
|
+
onClick: () => {
|
|
38009
|
+
forEachSelected((c, r) => duplicateRequest(c, r));
|
|
38010
|
+
selectionCtx.clear();
|
|
38011
|
+
},
|
|
38012
|
+
className: "px-2 py-0.5 rounded hover:bg-surface-800 text-surface-300 transition-colors",
|
|
38013
|
+
children: "Duplicate"
|
|
38014
|
+
}
|
|
38015
|
+
),
|
|
38016
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
38017
|
+
"button",
|
|
38018
|
+
{
|
|
38019
|
+
onClick: () => confirmThen(
|
|
38020
|
+
`Delete ${selected.size} request${selected.size === 1 ? "" : "s"}?`,
|
|
38021
|
+
() => {
|
|
38022
|
+
forEachSelected((c, r) => deleteRequest(c, r));
|
|
38023
|
+
selectionCtx.clear();
|
|
38024
|
+
}
|
|
38025
|
+
),
|
|
38026
|
+
className: "px-2 py-0.5 rounded hover:bg-red-900/40 text-red-400 transition-colors",
|
|
38027
|
+
children: "Delete"
|
|
38028
|
+
}
|
|
38029
|
+
),
|
|
38030
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
38031
|
+
"button",
|
|
38032
|
+
{
|
|
38033
|
+
onClick: selectionCtx.clear,
|
|
38034
|
+
className: "px-1.5 py-0.5 rounded hover:bg-surface-800 text-surface-500 transition-colors",
|
|
38035
|
+
title: "Clear selection",
|
|
38036
|
+
children: "×"
|
|
38037
|
+
}
|
|
38038
|
+
)
|
|
37133
38039
|
] })
|
|
37134
|
-
] }) });
|
|
38040
|
+
] }) }) });
|
|
37135
38041
|
}
|
|
37136
38042
|
function CollectionNode({
|
|
37137
38043
|
col,
|
|
@@ -37163,6 +38069,7 @@ function CollectionNode({
|
|
|
37163
38069
|
const [renaming, setRenaming] = reactExports.useState(false);
|
|
37164
38070
|
const [showSettings, setShowSettings] = reactExports.useState(false);
|
|
37165
38071
|
const [showSchemaSync, setShowSchemaSync] = reactExports.useState(false);
|
|
38072
|
+
const [showPushContract, setShowPushContract] = reactExports.useState(false);
|
|
37166
38073
|
const [expandCtrl, setExpandCtrl] = reactExports.useState({ value: true, seq: 0 });
|
|
37167
38074
|
const [dropOver, setDropOver] = reactExports.useState(false);
|
|
37168
38075
|
const dragCtx = reactExports.useContext(DragCtx);
|
|
@@ -37219,6 +38126,7 @@ function CollectionNode({
|
|
|
37219
38126
|
{ type: "item", label: "Collection data", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TableIcon, {}), onClick: onSelectCollection },
|
|
37220
38127
|
{ type: "item", label: "Settings", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(GearIcon, {}), onClick: () => setShowSettings(true) },
|
|
37221
38128
|
{ type: "item", label: "Sync schemas", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowSchemaSync(true) },
|
|
38129
|
+
...cloudEnabled() ? [{ type: "item", label: "Push contract to cloud", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowPushContract(true) }] : [],
|
|
37222
38130
|
{ type: "item", label: "Rename", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(PencilIcon, {}), onClick: () => setRenaming(true) },
|
|
37223
38131
|
{ type: "item", label: "Duplicate", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: onDuplicateCollection },
|
|
37224
38132
|
{ type: "separator" },
|
|
@@ -37253,6 +38161,14 @@ function CollectionNode({
|
|
|
37253
38161
|
onRunFolder
|
|
37254
38162
|
}
|
|
37255
38163
|
),
|
|
38164
|
+
showPushContract && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
38165
|
+
PushContractModal,
|
|
38166
|
+
{
|
|
38167
|
+
requests: collectTagged(col.rootFolder, col.requests, col.collectionVariables ?? {}, []).map((c) => c.request),
|
|
38168
|
+
defaultConsumer: col.name,
|
|
38169
|
+
onClose: () => setShowPushContract(false)
|
|
38170
|
+
}
|
|
38171
|
+
),
|
|
37256
38172
|
showSettings && /* @__PURE__ */ jsxRuntimeExports.jsx(CollectionSettingsModal, { collection: col, onClose: () => setShowSettings(false) }),
|
|
37257
38173
|
showSchemaSync && /* @__PURE__ */ jsxRuntimeExports.jsx(SchemaSyncModal, { collectionId: col.id, scope: { type: "collection" }, onClose: () => setShowSchemaSync(false) })
|
|
37258
38174
|
] });
|
|
@@ -37280,7 +38196,9 @@ function FolderRow({
|
|
|
37280
38196
|
const [renaming, setRenaming] = reactExports.useState(false);
|
|
37281
38197
|
const [showSettings, setShowSettings] = reactExports.useState(false);
|
|
37282
38198
|
const [showSchemaSync, setShowSchemaSync] = reactExports.useState(false);
|
|
38199
|
+
const [showPushContract, setShowPushContract] = reactExports.useState(false);
|
|
37283
38200
|
const [addingTag, setAddingTag] = reactExports.useState(false);
|
|
38201
|
+
const folderCollection = useStore((s) => s.collections[collectionId]?.data);
|
|
37284
38202
|
const [dropPos, setDropPos] = reactExports.useState(null);
|
|
37285
38203
|
const dragCtx = reactExports.useContext(DragCtx);
|
|
37286
38204
|
const tags2 = folder.tags ?? [];
|
|
@@ -37374,6 +38292,7 @@ function FolderRow({
|
|
|
37374
38292
|
{ type: "separator" },
|
|
37375
38293
|
{ type: "item", label: "Settings", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(KeyIcon, {}), onClick: () => setShowSettings(true) },
|
|
37376
38294
|
{ type: "item", label: "Sync schemas", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowSchemaSync(true) },
|
|
38295
|
+
...cloudEnabled() ? [{ type: "item", label: "Push contract to cloud", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowPushContract(true) }] : [],
|
|
37377
38296
|
{ type: "item", label: "Add tag", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TagIcon, {}), onClick: () => setAddingTag(true) },
|
|
37378
38297
|
{ type: "item", label: "Rename", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(PencilIcon, {}), onClick: () => setRenaming(true) },
|
|
37379
38298
|
{ type: "item", label: "Duplicate", icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: onDuplicate },
|
|
@@ -37384,6 +38303,14 @@ function FolderRow({
|
|
|
37384
38303
|
}
|
|
37385
38304
|
),
|
|
37386
38305
|
expanded && children,
|
|
38306
|
+
showPushContract && folderCollection && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
38307
|
+
PushContractModal,
|
|
38308
|
+
{
|
|
38309
|
+
requests: collectTagged(folder, folderCollection.requests, {}, []).map((c) => c.request),
|
|
38310
|
+
defaultConsumer: folder.name,
|
|
38311
|
+
onClose: () => setShowPushContract(false)
|
|
38312
|
+
}
|
|
38313
|
+
),
|
|
37387
38314
|
showSettings && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37388
38315
|
FolderSettingsModal,
|
|
37389
38316
|
{
|
|
@@ -37425,6 +38352,15 @@ function FolderContents({
|
|
|
37425
38352
|
onToggleRequestDisabled,
|
|
37426
38353
|
onRunFolder
|
|
37427
38354
|
}) {
|
|
38355
|
+
const activeExampleId = useStore((s) => {
|
|
38356
|
+
const t2 = s.tabs.find((x) => x.id === s.activeTabId);
|
|
38357
|
+
return t2?.exampleId ?? null;
|
|
38358
|
+
});
|
|
38359
|
+
const addExampleFromRequest = useStore((s) => s.addExampleFromRequest);
|
|
38360
|
+
const openExample = useStore((s) => s.openExample);
|
|
38361
|
+
const renameExample = useStore((s) => s.renameExample);
|
|
38362
|
+
const deleteExample = useStore((s) => s.deleteExample);
|
|
38363
|
+
const duplicateExample = useStore((s) => s.duplicateExample);
|
|
37428
38364
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
37429
38365
|
folder.folders.map((sub, subIndex) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37430
38366
|
FolderRow,
|
|
@@ -37492,206 +38428,61 @@ function FolderContents({
|
|
|
37492
38428
|
isActive: req.id === activeRequestId,
|
|
37493
38429
|
autoRename: req.id === newRequestId,
|
|
37494
38430
|
indent: (depth + 1) * 12 + 8,
|
|
38431
|
+
examples: req.examples?.map((e) => ({ id: e.id, name: e.name })),
|
|
38432
|
+
activeExampleId: req.id === activeRequestId ? activeExampleId : null,
|
|
37495
38433
|
onSelect: () => onSelectRequest(req.id),
|
|
37496
38434
|
onRename: (name2) => onRenameRequest(req.id, name2),
|
|
37497
38435
|
onDelete: () => onDeleteRequest(req.id),
|
|
37498
38436
|
onDuplicate: () => onDuplicateRequest(req.id),
|
|
37499
38437
|
onUpdateTags: (tags2) => onUpdateRequestTags(req.id, tags2),
|
|
37500
38438
|
onSetHookType: (ht) => onSetRequestHookType(req.id, ht),
|
|
37501
|
-
onToggleDisabled: () => onToggleRequestDisabled(req.id)
|
|
38439
|
+
onToggleDisabled: () => onToggleRequestDisabled(req.id),
|
|
38440
|
+
onAddExample: () => {
|
|
38441
|
+
const exId = addExampleFromRequest(req.id);
|
|
38442
|
+
if (exId) openExample(req.id, collectionId, exId);
|
|
38443
|
+
},
|
|
38444
|
+
onOpenExample: (exId) => openExample(req.id, collectionId, exId),
|
|
38445
|
+
onRenameExample: (exId, name2) => renameExample(req.id, exId, name2),
|
|
38446
|
+
onDeleteExample: (exId) => deleteExample(req.id, exId),
|
|
38447
|
+
onDuplicateExample: (exId) => duplicateExample(req.id, exId)
|
|
37502
38448
|
},
|
|
37503
38449
|
req.id
|
|
37504
38450
|
);
|
|
37505
38451
|
})
|
|
37506
38452
|
] });
|
|
37507
38453
|
}
|
|
37508
|
-
function
|
|
37509
|
-
|
|
37510
|
-
|
|
37511
|
-
|
|
37512
|
-
|
|
37513
|
-
}
|
|
37514
|
-
|
|
37515
|
-
|
|
37516
|
-
|
|
37517
|
-
return {
|
|
37518
|
-
|
|
37519
|
-
|
|
37520
|
-
|
|
37521
|
-
const
|
|
37522
|
-
|
|
37523
|
-
|
|
37524
|
-
|
|
37525
|
-
|
|
37526
|
-
const
|
|
37527
|
-
const
|
|
37528
|
-
|
|
37529
|
-
|
|
37530
|
-
|
|
37531
|
-
|
|
37532
|
-
|
|
37533
|
-
|
|
37534
|
-
const tags2 = req.meta?.tags ?? [];
|
|
37535
|
-
if (filterTags.length > 0 && !filterTags.some((t2) => tags2.includes(t2))) continue;
|
|
37536
|
-
for (const w of allWrappers) {
|
|
37537
|
-
for (const hookReq of w.before) {
|
|
37538
|
-
result.push(makeHook(hookReq, collectionVars, "before", w.scopeId, w.ancestors, w.scopePath, req.id));
|
|
37539
|
-
}
|
|
37540
|
-
}
|
|
37541
|
-
result.push({ request: req, collectionVars, scopeId, scopeAncestors: ancestorIds, scopePath });
|
|
37542
|
-
for (const w of [...allWrappers].reverse()) {
|
|
37543
|
-
for (const hookReq of w.after) {
|
|
37544
|
-
result.push(makeHook(hookReq, collectionVars, "after", w.scopeId, w.ancestors, w.scopePath, req.id));
|
|
37545
|
-
}
|
|
37546
|
-
}
|
|
37547
|
-
}
|
|
37548
|
-
for (const sub of folder.folders) {
|
|
37549
|
-
const folderTags = sub.tags ?? [];
|
|
37550
|
-
const effectiveFilter = filterTags.length === 0 ? filterTags : folderTags.some((t2) => filterTags.includes(t2)) ? [] : filterTags;
|
|
37551
|
-
result.push(...buildFolderPlan(
|
|
37552
|
-
sub,
|
|
37553
|
-
requests,
|
|
37554
|
-
collectionVars,
|
|
37555
|
-
effectiveFilter,
|
|
37556
|
-
sub.id,
|
|
37557
|
-
[...ancestorIds, scopeId],
|
|
37558
|
-
scopePath,
|
|
37559
|
-
allWrappers,
|
|
37560
|
-
false
|
|
37561
|
-
));
|
|
37562
|
-
}
|
|
37563
|
-
for (const req of afterAllHooks) {
|
|
37564
|
-
result.push(makeHook(req, collectionVars, "afterAll", scopeId, ancestorIds, scopePath));
|
|
37565
|
-
}
|
|
37566
|
-
return result;
|
|
37567
|
-
}
|
|
37568
|
-
function collectAllTags(folder, requests) {
|
|
37569
|
-
const tags2 = /* @__PURE__ */ new Set();
|
|
37570
|
-
function walk(f) {
|
|
37571
|
-
(f.tags ?? []).forEach((t2) => tags2.add(t2));
|
|
37572
|
-
for (const reqId of f.requestIds) {
|
|
37573
|
-
(requests[reqId]?.meta?.tags ?? []).forEach((t2) => tags2.add(t2));
|
|
37574
|
-
}
|
|
37575
|
-
f.folders.forEach(walk);
|
|
37576
|
-
}
|
|
37577
|
-
walk(folder);
|
|
37578
|
-
return Array.from(tags2).sort();
|
|
37579
|
-
}
|
|
37580
|
-
function folderPathTo(root2, requestId) {
|
|
37581
|
-
if (root2.requestIds.includes(requestId)) return [root2];
|
|
37582
|
-
for (const sub of root2.folders) {
|
|
37583
|
-
const path = folderPathTo(sub, requestId);
|
|
37584
|
-
if (path.length > 0) return [root2, ...path];
|
|
37585
|
-
}
|
|
37586
|
-
return [];
|
|
37587
|
-
}
|
|
37588
|
-
function getHooksForRequest(requestId, collection) {
|
|
37589
|
-
const path = folderPathTo(collection.rootFolder, requestId);
|
|
37590
|
-
const before = [];
|
|
37591
|
-
const afterReversed = [];
|
|
37592
|
-
for (const folder of path) {
|
|
37593
|
-
const reqs = folder.requestIds.map((id2) => collection.requests[id2]).filter((r) => r && !r.disabled);
|
|
37594
|
-
const bAll = reqs.filter((r) => r.hookType === "beforeAll");
|
|
37595
|
-
const bEach = reqs.filter((r) => r.hookType === "before");
|
|
37596
|
-
const aEach = reqs.filter((r) => r.hookType === "after");
|
|
37597
|
-
const aAll = reqs.filter((r) => r.hookType === "afterAll");
|
|
37598
|
-
before.push(...bAll, ...bEach);
|
|
37599
|
-
afterReversed.push(...aEach, ...aAll);
|
|
37600
|
-
}
|
|
37601
|
-
return { before, after: afterReversed.reverse() };
|
|
37602
|
-
}
|
|
37603
|
-
function authIsConfigured(auth) {
|
|
37604
|
-
if (!auth || auth.type === "none") return false;
|
|
37605
|
-
const set2 = (s) => !!(s && s.trim());
|
|
37606
|
-
switch (auth.type) {
|
|
37607
|
-
case "bearer":
|
|
37608
|
-
return set2(auth.token) || set2(auth.tokenSecretRef);
|
|
37609
|
-
case "basic":
|
|
37610
|
-
case "digest":
|
|
37611
|
-
return set2(auth.username) || set2(auth.password) || set2(auth.passwordSecretRef);
|
|
37612
|
-
case "ntlm":
|
|
37613
|
-
return set2(auth.username) || set2(auth.password) || set2(auth.passwordSecretRef);
|
|
37614
|
-
case "apikey":
|
|
37615
|
-
return set2(auth.apiKeyValue) || set2(auth.apiKeySecretRef);
|
|
37616
|
-
case "oauth2":
|
|
37617
|
-
return set2(auth.oauth2TokenUrl) || set2(auth.oauth2ClientId) || set2(auth.oauth2CachedToken);
|
|
37618
|
-
default:
|
|
37619
|
-
return true;
|
|
37620
|
-
}
|
|
37621
|
-
}
|
|
37622
|
-
function resolveInheritedAuthAndHeaders(requestId, collection) {
|
|
37623
|
-
let inheritedAuth = collection.auth && collection.auth.type !== "none" ? collection.auth : null;
|
|
37624
|
-
let inheritedHeaders = collection.headers?.filter((h) => h.enabled && h.key) ?? [];
|
|
37625
|
-
const path = folderPathTo(collection.rootFolder, requestId);
|
|
37626
|
-
for (const folder of path) {
|
|
37627
|
-
if (folder.auth && folder.auth.type !== "none") inheritedAuth = folder.auth;
|
|
37628
|
-
if (folder.headers?.length) {
|
|
37629
|
-
inheritedHeaders = [...inheritedHeaders, ...folder.headers.filter((h) => h.enabled && h.key)];
|
|
37630
|
-
}
|
|
37631
|
-
}
|
|
37632
|
-
return { auth: inheritedAuth, headers: inheritedHeaders };
|
|
37633
|
-
}
|
|
37634
|
-
function buildRunPlan(collection, folderId, filterTags) {
|
|
37635
|
-
const collectionVars = collection.collectionVariables ?? {};
|
|
37636
|
-
if (!folderId) {
|
|
37637
|
-
return buildFolderPlan(
|
|
37638
|
-
collection.rootFolder,
|
|
37639
|
-
collection.requests,
|
|
37640
|
-
collectionVars,
|
|
37641
|
-
filterTags,
|
|
37642
|
-
collection.rootFolder.id,
|
|
37643
|
-
[],
|
|
37644
|
-
[],
|
|
37645
|
-
[],
|
|
37646
|
-
true
|
|
37647
|
-
);
|
|
37648
|
-
}
|
|
37649
|
-
const chain = folderChainTo(collection.rootFolder, folderId);
|
|
37650
|
-
if (chain.length === 0) return [];
|
|
37651
|
-
const targetFolder = chain[chain.length - 1];
|
|
37652
|
-
const ancestors = chain.slice(0, -1);
|
|
37653
|
-
const result = [];
|
|
37654
|
-
const ancestorWrappers = [];
|
|
37655
|
-
const ancestorIds = [];
|
|
37656
|
-
for (const f of ancestors) {
|
|
37657
|
-
const reqs = f.requestIds.map((id2) => collection.requests[id2]).filter((r) => r && !r.disabled);
|
|
37658
|
-
const beforeAllH = reqs.filter((r) => r.hookType === "beforeAll");
|
|
37659
|
-
const beforeH = reqs.filter((r) => r.hookType === "before");
|
|
37660
|
-
const afterH = reqs.filter((r) => r.hookType === "after");
|
|
37661
|
-
for (const req of beforeAllH) {
|
|
37662
|
-
result.push(makeHook(req, collectionVars, "beforeAll", f.id, [...ancestorIds], []));
|
|
37663
|
-
}
|
|
37664
|
-
ancestorWrappers.push({
|
|
37665
|
-
scopeId: f.id,
|
|
37666
|
-
ancestors: [...ancestorIds],
|
|
37667
|
-
scopePath: [],
|
|
37668
|
-
// ancestor hooks render with no folder heading
|
|
37669
|
-
before: beforeH,
|
|
37670
|
-
after: afterH
|
|
37671
|
-
});
|
|
37672
|
-
ancestorIds.push(f.id);
|
|
37673
|
-
}
|
|
37674
|
-
result.push(...buildFolderPlan(
|
|
37675
|
-
targetFolder,
|
|
37676
|
-
collection.requests,
|
|
37677
|
-
collectionVars,
|
|
37678
|
-
filterTags,
|
|
37679
|
-
targetFolder.id,
|
|
37680
|
-
ancestorIds,
|
|
37681
|
-
[],
|
|
37682
|
-
ancestorWrappers,
|
|
37683
|
-
true
|
|
37684
|
-
));
|
|
37685
|
-
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
37686
|
-
const f = ancestors[i];
|
|
37687
|
-
const reqs = f.requestIds.map((id2) => collection.requests[id2]).filter((r) => r && !r.disabled);
|
|
37688
|
-
const afterAllH = reqs.filter((r) => r.hookType === "afterAll");
|
|
37689
|
-
const myAncestors = ancestorIds.slice(0, i);
|
|
37690
|
-
for (const req of afterAllH) {
|
|
37691
|
-
result.push(makeHook(req, collectionVars, "afterAll", f.id, myAncestors, []));
|
|
37692
|
-
}
|
|
38454
|
+
function safeDecode(s) {
|
|
38455
|
+
try {
|
|
38456
|
+
return decodeURIComponent(s);
|
|
38457
|
+
} catch {
|
|
38458
|
+
return s;
|
|
38459
|
+
}
|
|
38460
|
+
}
|
|
38461
|
+
function extractQueryParams(rawUrl, existing) {
|
|
38462
|
+
const qIdx = rawUrl.indexOf("?");
|
|
38463
|
+
if (qIdx === -1) return { url: rawUrl, params: existing, changed: false };
|
|
38464
|
+
const base2 = rawUrl.slice(0, qIdx);
|
|
38465
|
+
let query = rawUrl.slice(qIdx + 1);
|
|
38466
|
+
let fragment = "";
|
|
38467
|
+
const hashIdx = query.indexOf("#");
|
|
38468
|
+
if (hashIdx !== -1) {
|
|
38469
|
+
fragment = query.slice(hashIdx);
|
|
38470
|
+
query = query.slice(0, hashIdx);
|
|
38471
|
+
}
|
|
38472
|
+
const parsed = [];
|
|
38473
|
+
for (const pair2 of query.split("&")) {
|
|
38474
|
+
if (!pair2) continue;
|
|
38475
|
+
const eq = pair2.indexOf("=");
|
|
38476
|
+
const key = safeDecode(eq === -1 ? pair2 : pair2.slice(0, eq));
|
|
38477
|
+
if (!key) continue;
|
|
38478
|
+
const value = eq === -1 ? "" : safeDecode(pair2.slice(eq + 1));
|
|
38479
|
+
parsed.push({ key, value, enabled: true });
|
|
37693
38480
|
}
|
|
37694
|
-
|
|
38481
|
+
const nextUrl = base2 + fragment;
|
|
38482
|
+
if (parsed.length === 0) return { url: nextUrl, params: existing, changed: nextUrl !== rawUrl };
|
|
38483
|
+
const pastedKeys = new Set(parsed.map((p2) => p2.key));
|
|
38484
|
+
const kept = (existing ?? []).filter((p2) => (p2.key || p2.value) && !pastedKeys.has(p2.key));
|
|
38485
|
+
return { url: nextUrl, params: [...kept, ...parsed], changed: true };
|
|
37695
38486
|
}
|
|
37696
38487
|
function ParamsTab({ request, onChange }) {
|
|
37697
38488
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -42951,6 +43742,393 @@ const jsonLanguage = /* @__PURE__ */ LRLanguage.define({
|
|
|
42951
43742
|
function json() {
|
|
42952
43743
|
return new LanguageSupport(jsonLanguage);
|
|
42953
43744
|
}
|
|
43745
|
+
const StartTag = 1, StartCloseTag = 2, MissingCloseTag = 3, mismatchedStartCloseTag = 4, incompleteStartCloseTag = 5, commentContent$1 = 36, piContent$1 = 37, cdataContent$1 = 38, Element$1 = 11, OpenTag = 13;
|
|
43746
|
+
function nameChar(ch) {
|
|
43747
|
+
return ch == 45 || ch == 46 || ch == 58 || ch >= 65 && ch <= 90 || ch == 95 || ch >= 97 && ch <= 122 || ch >= 161;
|
|
43748
|
+
}
|
|
43749
|
+
function isSpace(ch) {
|
|
43750
|
+
return ch == 9 || ch == 10 || ch == 13 || ch == 32;
|
|
43751
|
+
}
|
|
43752
|
+
let cachedName = null, cachedInput = null, cachedPos = 0;
|
|
43753
|
+
function tagNameAfter(input, offset) {
|
|
43754
|
+
let pos = input.pos + offset;
|
|
43755
|
+
if (cachedInput == input && cachedPos == pos) return cachedName;
|
|
43756
|
+
while (isSpace(input.peek(offset))) offset++;
|
|
43757
|
+
let name2 = "";
|
|
43758
|
+
for (; ; ) {
|
|
43759
|
+
let next = input.peek(offset);
|
|
43760
|
+
if (!nameChar(next)) break;
|
|
43761
|
+
name2 += String.fromCharCode(next);
|
|
43762
|
+
offset++;
|
|
43763
|
+
}
|
|
43764
|
+
cachedInput = input;
|
|
43765
|
+
cachedPos = pos;
|
|
43766
|
+
return cachedName = name2 || null;
|
|
43767
|
+
}
|
|
43768
|
+
function ElementContext(name2, parent) {
|
|
43769
|
+
this.name = name2;
|
|
43770
|
+
this.parent = parent;
|
|
43771
|
+
}
|
|
43772
|
+
const elementContext = new ContextTracker({
|
|
43773
|
+
start: null,
|
|
43774
|
+
shift(context, term, stack, input) {
|
|
43775
|
+
return term == StartTag ? new ElementContext(tagNameAfter(input, 1) || "", context) : context;
|
|
43776
|
+
},
|
|
43777
|
+
reduce(context, term) {
|
|
43778
|
+
return term == Element$1 && context ? context.parent : context;
|
|
43779
|
+
},
|
|
43780
|
+
reuse(context, node, _stack, input) {
|
|
43781
|
+
let type2 = node.type.id;
|
|
43782
|
+
return type2 == StartTag || type2 == OpenTag ? new ElementContext(tagNameAfter(input, 1) || "", context) : context;
|
|
43783
|
+
},
|
|
43784
|
+
strict: false
|
|
43785
|
+
});
|
|
43786
|
+
const startTag = new ExternalTokenizer((input, stack) => {
|
|
43787
|
+
if (input.next != 60) return;
|
|
43788
|
+
input.advance();
|
|
43789
|
+
if (input.next == 47) {
|
|
43790
|
+
input.advance();
|
|
43791
|
+
let name2 = tagNameAfter(input, 0);
|
|
43792
|
+
if (!name2) return input.acceptToken(incompleteStartCloseTag);
|
|
43793
|
+
if (stack.context && name2 == stack.context.name) return input.acceptToken(StartCloseTag);
|
|
43794
|
+
for (let cx = stack.context; cx; cx = cx.parent) if (cx.name == name2) return input.acceptToken(MissingCloseTag, -2);
|
|
43795
|
+
input.acceptToken(mismatchedStartCloseTag);
|
|
43796
|
+
} else if (input.next != 33 && input.next != 63) {
|
|
43797
|
+
return input.acceptToken(StartTag);
|
|
43798
|
+
}
|
|
43799
|
+
}, { contextual: true });
|
|
43800
|
+
function scanTo(type2, end) {
|
|
43801
|
+
return new ExternalTokenizer((input) => {
|
|
43802
|
+
let len = 0, first = end.charCodeAt(0);
|
|
43803
|
+
scan: for (; ; input.advance(), len++) {
|
|
43804
|
+
if (input.next < 0) break;
|
|
43805
|
+
if (input.next == first) {
|
|
43806
|
+
for (let i = 1; i < end.length; i++)
|
|
43807
|
+
if (input.peek(i) != end.charCodeAt(i)) continue scan;
|
|
43808
|
+
break;
|
|
43809
|
+
}
|
|
43810
|
+
}
|
|
43811
|
+
if (len) input.acceptToken(type2);
|
|
43812
|
+
});
|
|
43813
|
+
}
|
|
43814
|
+
const commentContent = scanTo(commentContent$1, "-->");
|
|
43815
|
+
const piContent = scanTo(piContent$1, "?>");
|
|
43816
|
+
const cdataContent = scanTo(cdataContent$1, "]]>");
|
|
43817
|
+
const xmlHighlighting = styleTags({
|
|
43818
|
+
Text: tags.content,
|
|
43819
|
+
"StartTag StartCloseTag EndTag SelfCloseEndTag": tags.angleBracket,
|
|
43820
|
+
TagName: tags.tagName,
|
|
43821
|
+
"MismatchedCloseTag/TagName": [tags.tagName, tags.invalid],
|
|
43822
|
+
AttributeName: tags.attributeName,
|
|
43823
|
+
AttributeValue: tags.attributeValue,
|
|
43824
|
+
Is: tags.definitionOperator,
|
|
43825
|
+
"EntityReference CharacterReference": tags.character,
|
|
43826
|
+
Comment: tags.blockComment,
|
|
43827
|
+
ProcessingInst: tags.processingInstruction,
|
|
43828
|
+
DoctypeDecl: tags.documentMeta,
|
|
43829
|
+
Cdata: tags.special(tags.string)
|
|
43830
|
+
});
|
|
43831
|
+
const parser$2 = LRParser.deserialize({
|
|
43832
|
+
version: 14,
|
|
43833
|
+
states: ",lOQOaOOOrOxO'#CfOzOpO'#CiO!tOaO'#CgOOOP'#Cg'#CgO!{OrO'#CrO#TOtO'#CsO#]OpO'#CtOOOP'#DT'#DTOOOP'#Cv'#CvQQOaOOOOOW'#Cw'#CwO#eOxO,59QOOOP,59Q,59QOOOO'#Cx'#CxO#mOpO,59TO#uO!bO,59TOOOP'#C|'#C|O$TOaO,59RO$[OpO'#CoOOOP,59R,59ROOOQ'#C}'#C}O$dOrO,59^OOOP,59^,59^OOOS'#DO'#DOO$lOtO,59_OOOP,59_,59_O$tOpO,59`O$|OpO,59`OOOP-E6t-E6tOOOW-E6u-E6uOOOP1G.l1G.lOOOO-E6v-E6vO%UO!bO1G.oO%UO!bO1G.oO%dOpO'#CkO%lO!bO'#CyO%zO!bO1G.oOOOP1G.o1G.oOOOP1G.w1G.wOOOP-E6z-E6zOOOP1G.m1G.mO&VOpO,59ZO&_OpO,59ZOOOQ-E6{-E6{OOOP1G.x1G.xOOOS-E6|-E6|OOOP1G.y1G.yO&gOpO1G.zO&gOpO1G.zOOOP1G.z1G.zO&oO!bO7+$ZO&}O!bO7+$ZOOOP7+$Z7+$ZOOOP7+$c7+$cO'YOpO,59VO'bOpO,59VO'mO!bO,59eOOOO-E6w-E6wO'{OpO1G.uO'{OpO1G.uOOOP1G.u1G.uO(TOpO7+$fOOOP7+$f7+$fO(]O!bO<<GuOOOP<<Gu<<GuOOOP<<G}<<G}O'bOpO1G.qO'bOpO1G.qO(hO#tO'#CnO(vO&jO'#CnOOOO1G.q1G.qO)UOpO7+$aOOOP7+$a7+$aOOOP<<HQ<<HQOOOPAN=aAN=aOOOPAN=iAN=iO'bOpO7+$]OOOO7+$]7+$]OOOO'#Cz'#CzO)^O#tO,59YOOOO,59Y,59YOOOO'#C{'#C{O)lO&jO,59YOOOP<<G{<<G{OOOO<<Gw<<GwOOOO-E6x-E6xOOOO1G.t1G.tOOOO-E6y-E6y",
|
|
43834
|
+
stateData: ")z~OPQOSVOTWOVWOWWOXWOiXOyPO!QTO!SUO~OvZOx]O~O^`Oz^O~OPQOQcOSVOTWOVWOWWOXWOyPO!QTO!SUO~ORdO~P!SOteO!PgO~OuhO!RjO~O^lOz^O~OvZOxoO~O^qOz^O~O[vO`sOdwOz^O~ORyO~P!SO^{Oz^O~OteO!P}O~OuhO!R!PO~O^!QOz^O~O[!SOz^O~O[!VO`sOd!WOz^O~Oa!YOz^O~Oz^O[mX`mXdmX~O[!VO`sOd!WO~O^!]Oz^O~O[!_Oz^O~O[!aOz^O~O[!cO`sOd!dOz^O~O[!cO`sOd!dO~Oa!eOz^O~Oz^O{!gO}!hO~Oz^O[ma`madma~O[!kOz^O~O[!lOz^O~O[!mO`sOd!nO~OW!qOX!qO{!sO|!qO~OW!tOX!tO}!sO!O!tO~O[!vOz^O~OW!qOX!qO{!yO|!qO~OW!tOX!tO}!yO!O!tO~O",
|
|
43835
|
+
goto: "%cxPPPPPPPPPPyyP!PP!VPP!`!jP!pyyyP!v!|#S$[$k$q$w$}%TPPPP%ZXWORYbXRORYb_t`qru!T!U!bQ!i!YS!p!e!fR!w!oQdRRybXSORYbQYORmYQ[PRn[Q_QQkVjp_krz!R!T!X!Z!^!`!f!j!oQr`QzcQ!RlQ!TqQ!XsQ!ZtQ!^{Q!`!QQ!f!YQ!j!]R!o!eQu`S!UqrU![u!U!bR!b!TQ!r!gR!x!rQ!u!hR!z!uQbRRxbQfTR|fQiUR!OiSXOYTaRb",
|
|
43836
|
+
nodeNames: "⚠ StartTag StartCloseTag MissingCloseTag StartCloseTag StartCloseTag Document Text EntityReference CharacterReference Cdata Element EndTag OpenTag TagName Attribute AttributeName Is AttributeValue CloseTag SelfCloseEndTag SelfClosingTag Comment ProcessingInst MismatchedCloseTag DoctypeDecl",
|
|
43837
|
+
maxTerm: 50,
|
|
43838
|
+
context: elementContext,
|
|
43839
|
+
nodeProps: [
|
|
43840
|
+
["closedBy", 1, "SelfCloseEndTag EndTag", 13, "CloseTag MissingCloseTag"],
|
|
43841
|
+
["openedBy", 12, "StartTag StartCloseTag", 19, "OpenTag", 20, "StartTag"],
|
|
43842
|
+
["isolate", -6, 13, 18, 19, 21, 22, 24, ""]
|
|
43843
|
+
],
|
|
43844
|
+
propSources: [xmlHighlighting],
|
|
43845
|
+
skippedNodes: [0],
|
|
43846
|
+
repeatNodeCount: 9,
|
|
43847
|
+
tokenData: "!)v~R!YOX$qXY)iYZ)iZ]$q]^)i^p$qpq)iqr$qrs*vsv$qvw+fwx/ix}$q}!O0[!O!P$q!P!Q2z!Q![$q![!]4n!]!^$q!^!_8U!_!`!#t!`!a!$l!a!b!%d!b!c$q!c!}4n!}#P$q#P#Q!'W#Q#R$q#R#S4n#S#T$q#T#o4n#o%W$q%W%o4n%o%p$q%p&a4n&a&b$q&b1p4n1p4U$q4U4d4n4d4e$q4e$IS4n$IS$I`$q$I`$Ib4n$Ib$Kh$q$Kh%#t4n%#t&/x$q&/x&Et4n&Et&FV$q&FV;'S4n;'S;:j8O;:j;=`)c<%l?&r$q?&r?Ah4n?Ah?BY$q?BY?Mn4n?MnO$qi$zXVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qa%nVVP!O`Ov%gwx&Tx!^%g!^!_&o!_;'S%g;'S;=`'W<%lO%gP&YTVPOv&Tw!^&T!_;'S&T;'S;=`&i<%lO&TP&lP;=`<%l&T`&tS!O`Ov&ox;'S&o;'S;=`'Q<%lO&o`'TP;=`<%l&oa'ZP;=`<%l%gX'eWVP|WOr'^rs&Tsv'^w!^'^!^!_'}!_;'S'^;'S;=`(i<%lO'^W(ST|WOr'}sv'}w;'S'};'S;=`(c<%lO'}W(fP;=`<%l'}X(lP;=`<%l'^h(vV|W!O`Or(ors&osv(owx'}x;'S(o;'S;=`)]<%lO(oh)`P;=`<%l(oi)fP;=`<%l$qo)t`VP|W!O`zUOX$qXY)iYZ)iZ]$q]^)i^p$qpq)iqr$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qk+PV{YVP!O`Ov%gwx&Tx!^%g!^!_&o!_;'S%g;'S;=`'W<%lO%g~+iast,n![!]-r!c!}-r#R#S-r#T#o-r%W%o-r%p&a-r&b1p-r4U4d-r4e$IS-r$I`$Ib-r$Kh%#t-r&/x&Et-r&FV;'S-r;'S;:j/c?&r?Ah-r?BY?Mn-r~,qQ!Q![,w#l#m-V~,zQ!Q![,w!]!^-Q~-VOX~~-YR!Q![-c!c!i-c#T#Z-c~-fS!Q![-c!]!^-Q!c!i-c#T#Z-c~-ug}!O-r!O!P-r!Q![-r![!]-r!]!^/^!c!}-r#R#S-r#T#o-r$}%O-r%W%o-r%p&a-r&b1p-r1p4U-r4U4d-r4e$IS-r$I`$Ib-r$Je$Jg-r$Kh%#t-r&/x&Et-r&FV;'S-r;'S;:j/c?&r?Ah-r?BY?Mn-r~/cOW~~/fP;=`<%l-rk/rW}bVP|WOr'^rs&Tsv'^w!^'^!^!_'}!_;'S'^;'S;=`(i<%lO'^k0eZVP|W!O`Or$qrs%gsv$qwx'^x}$q}!O1W!O!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qk1aZVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_!`$q!`!a2S!a;'S$q;'S;=`)c<%lO$qk2_X!PQVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qm3TZVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_!`$q!`!a3v!a;'S$q;'S;=`)c<%lO$qm4RXdSVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qo4{!P`S^QVP|W!O`Or$qrs%gsv$qwx'^x}$q}!O4n!O!P4n!P!Q$q!Q![4n![!]4n!]!^$q!^!_(o!_!c$q!c!}4n!}#R$q#R#S4n#S#T$q#T#o4n#o$}$q$}%O4n%O%W$q%W%o4n%o%p$q%p&a4n&a&b$q&b1p4n1p4U4n4U4d4n4d4e$q4e$IS4n$IS$I`$q$I`$Ib4n$Ib$Je$q$Je$Jg4n$Jg$Kh$q$Kh%#t4n%#t&/x$q&/x&Et4n&Et&FV$q&FV;'S4n;'S;:j8O;:j;=`)c<%l?&r$q?&r?Ah4n?Ah?BY$q?BY?Mn4n?MnO$qo8RP;=`<%l4ni8]Y|W!O`Oq(oqr8{rs&osv(owx'}x!a(o!a!b!#U!b;'S(o;'S;=`)]<%lO(oi9S_|W!O`Or(ors&osv(owx'}x}(o}!O:R!O!f(o!f!g;e!g!}(o!}#ODh#O#W(o#W#XLp#X;'S(o;'S;=`)]<%lO(oi:YX|W!O`Or(ors&osv(owx'}x}(o}!O:u!O;'S(o;'S;=`)]<%lO(oi;OV!QP|W!O`Or(ors&osv(owx'}x;'S(o;'S;=`)]<%lO(oi;lX|W!O`Or(ors&osv(owx'}x!q(o!q!r<X!r;'S(o;'S;=`)]<%lO(oi<`X|W!O`Or(ors&osv(owx'}x!e(o!e!f<{!f;'S(o;'S;=`)]<%lO(oi=SX|W!O`Or(ors&osv(owx'}x!v(o!v!w=o!w;'S(o;'S;=`)]<%lO(oi=vX|W!O`Or(ors&osv(owx'}x!{(o!{!|>c!|;'S(o;'S;=`)]<%lO(oi>jX|W!O`Or(ors&osv(owx'}x!r(o!r!s?V!s;'S(o;'S;=`)]<%lO(oi?^X|W!O`Or(ors&osv(owx'}x!g(o!g!h?y!h;'S(o;'S;=`)]<%lO(oi@QY|W!O`Or?yrs@psv?yvwA[wxBdx!`?y!`!aCr!a;'S?y;'S;=`Db<%lO?ya@uV!O`Ov@pvxA[x!`@p!`!aAy!a;'S@p;'S;=`B^<%lO@pPA_TO!`A[!`!aAn!a;'SA[;'S;=`As<%lOA[PAsOiPPAvP;=`<%lA[aBQSiP!O`Ov&ox;'S&o;'S;=`'Q<%lO&oaBaP;=`<%l@pXBiX|WOrBdrsA[svBdvwA[w!`Bd!`!aCU!a;'SBd;'S;=`Cl<%lOBdXC]TiP|WOr'}sv'}w;'S'};'S;=`(c<%lO'}XCoP;=`<%lBdiC{ViP|W!O`Or(ors&osv(owx'}x;'S(o;'S;=`)]<%lO(oiDeP;=`<%l?yiDoZ|W!O`Or(ors&osv(owx'}x!e(o!e!fEb!f#V(o#V#WIr#W;'S(o;'S;=`)]<%lO(oiEiX|W!O`Or(ors&osv(owx'}x!f(o!f!gFU!g;'S(o;'S;=`)]<%lO(oiF]X|W!O`Or(ors&osv(owx'}x!c(o!c!dFx!d;'S(o;'S;=`)]<%lO(oiGPX|W!O`Or(ors&osv(owx'}x!v(o!v!wGl!w;'S(o;'S;=`)]<%lO(oiGsX|W!O`Or(ors&osv(owx'}x!c(o!c!dH`!d;'S(o;'S;=`)]<%lO(oiHgX|W!O`Or(ors&osv(owx'}x!}(o!}#OIS#O;'S(o;'S;=`)]<%lO(oiI]V|W!O`yPOr(ors&osv(owx'}x;'S(o;'S;=`)]<%lO(oiIyX|W!O`Or(ors&osv(owx'}x#W(o#W#XJf#X;'S(o;'S;=`)]<%lO(oiJmX|W!O`Or(ors&osv(owx'}x#T(o#T#UKY#U;'S(o;'S;=`)]<%lO(oiKaX|W!O`Or(ors&osv(owx'}x#h(o#h#iK|#i;'S(o;'S;=`)]<%lO(oiLTX|W!O`Or(ors&osv(owx'}x#T(o#T#UH`#U;'S(o;'S;=`)]<%lO(oiLwX|W!O`Or(ors&osv(owx'}x#c(o#c#dMd#d;'S(o;'S;=`)]<%lO(oiMkX|W!O`Or(ors&osv(owx'}x#V(o#V#WNW#W;'S(o;'S;=`)]<%lO(oiN_X|W!O`Or(ors&osv(owx'}x#h(o#h#iNz#i;'S(o;'S;=`)]<%lO(oi! RX|W!O`Or(ors&osv(owx'}x#m(o#m#n! n#n;'S(o;'S;=`)]<%lO(oi! uX|W!O`Or(ors&osv(owx'}x#d(o#d#e!!b#e;'S(o;'S;=`)]<%lO(oi!!iX|W!O`Or(ors&osv(owx'}x#X(o#X#Y?y#Y;'S(o;'S;=`)]<%lO(oi!#_V!SP|W!O`Or(ors&osv(owx'}x;'S(o;'S;=`)]<%lO(ok!$PXaQVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qo!$wX[UVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qk!%mZVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_!`$q!`!a!&`!a;'S$q;'S;=`)c<%lO$qk!&kX!RQVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qk!'aZVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_#P$q#P#Q!(S#Q;'S$q;'S;=`)c<%lO$qk!(]ZVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_!`$q!`!a!)O!a;'S$q;'S;=`)c<%lO$qk!)ZXxQVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$q",
|
|
43848
|
+
tokenizers: [startTag, commentContent, piContent, cdataContent, 0, 1, 2, 3, 4],
|
|
43849
|
+
topRules: { "Document": [0, 6] },
|
|
43850
|
+
tokenPrec: 0
|
|
43851
|
+
});
|
|
43852
|
+
function tagName(doc2, tag) {
|
|
43853
|
+
let name2 = tag && tag.getChild("TagName");
|
|
43854
|
+
return name2 ? doc2.sliceString(name2.from, name2.to) : "";
|
|
43855
|
+
}
|
|
43856
|
+
function elementName$1(doc2, tree) {
|
|
43857
|
+
let tag = tree && tree.firstChild;
|
|
43858
|
+
return !tag || tag.name != "OpenTag" ? "" : tagName(doc2, tag);
|
|
43859
|
+
}
|
|
43860
|
+
function attrName(doc2, tag, pos) {
|
|
43861
|
+
let attr = tag && tag.getChildren("Attribute").find((a) => a.from <= pos && a.to >= pos);
|
|
43862
|
+
let name2 = attr && attr.getChild("AttributeName");
|
|
43863
|
+
return name2 ? doc2.sliceString(name2.from, name2.to) : "";
|
|
43864
|
+
}
|
|
43865
|
+
function findParentElement(tree) {
|
|
43866
|
+
for (let cur2 = tree && tree.parent; cur2; cur2 = cur2.parent)
|
|
43867
|
+
if (cur2.name == "Element")
|
|
43868
|
+
return cur2;
|
|
43869
|
+
return null;
|
|
43870
|
+
}
|
|
43871
|
+
function findLocation(state, pos) {
|
|
43872
|
+
var _a2;
|
|
43873
|
+
let at = syntaxTree(state).resolveInner(pos, -1), inTag = null;
|
|
43874
|
+
for (let cur2 = at; !inTag && cur2.parent; cur2 = cur2.parent)
|
|
43875
|
+
if (cur2.name == "OpenTag" || cur2.name == "CloseTag" || cur2.name == "SelfClosingTag" || cur2.name == "MismatchedCloseTag")
|
|
43876
|
+
inTag = cur2;
|
|
43877
|
+
if (inTag && (inTag.to > pos || inTag.lastChild.type.isError)) {
|
|
43878
|
+
let elt = inTag.parent;
|
|
43879
|
+
if (at.name == "TagName")
|
|
43880
|
+
return inTag.name == "CloseTag" || inTag.name == "MismatchedCloseTag" ? { type: "closeTag", from: at.from, context: elt } : { type: "openTag", from: at.from, context: findParentElement(elt) };
|
|
43881
|
+
if (at.name == "AttributeName")
|
|
43882
|
+
return { type: "attrName", from: at.from, context: inTag };
|
|
43883
|
+
if (at.name == "AttributeValue")
|
|
43884
|
+
return { type: "attrValue", from: at.from, context: inTag };
|
|
43885
|
+
let before = at == inTag || at.name == "Attribute" ? at.childBefore(pos) : at;
|
|
43886
|
+
if ((before === null || before === void 0 ? void 0 : before.name) == "StartTag")
|
|
43887
|
+
return { type: "openTag", from: pos, context: findParentElement(elt) };
|
|
43888
|
+
if ((before === null || before === void 0 ? void 0 : before.name) == "StartCloseTag" && before.to <= pos)
|
|
43889
|
+
return { type: "closeTag", from: pos, context: elt };
|
|
43890
|
+
if ((before === null || before === void 0 ? void 0 : before.name) == "Is")
|
|
43891
|
+
return { type: "attrValue", from: pos, context: inTag };
|
|
43892
|
+
if (before)
|
|
43893
|
+
return { type: "attrName", from: pos, context: inTag };
|
|
43894
|
+
return null;
|
|
43895
|
+
} else if (at.name == "StartCloseTag") {
|
|
43896
|
+
return { type: "closeTag", from: pos, context: at.parent };
|
|
43897
|
+
}
|
|
43898
|
+
while (at.parent && at.to == pos && !((_a2 = at.lastChild) === null || _a2 === void 0 ? void 0 : _a2.type.isError))
|
|
43899
|
+
at = at.parent;
|
|
43900
|
+
if (at.name == "Element" || at.name == "Text" || at.name == "Document")
|
|
43901
|
+
return { type: "tag", from: pos, context: at.name == "Element" ? at : findParentElement(at) };
|
|
43902
|
+
return null;
|
|
43903
|
+
}
|
|
43904
|
+
class Element {
|
|
43905
|
+
constructor(spec, attrs, attrValues) {
|
|
43906
|
+
this.attrs = attrs;
|
|
43907
|
+
this.attrValues = attrValues;
|
|
43908
|
+
this.children = [];
|
|
43909
|
+
this.name = spec.name;
|
|
43910
|
+
this.completion = Object.assign(Object.assign({ type: "type" }, spec.completion || {}), { label: this.name });
|
|
43911
|
+
this.openCompletion = Object.assign(Object.assign({}, this.completion), { label: "<" + this.name });
|
|
43912
|
+
this.closeCompletion = Object.assign(Object.assign({}, this.completion), { label: "</" + this.name + ">", boost: 2 });
|
|
43913
|
+
this.closeNameCompletion = Object.assign(Object.assign({}, this.completion), { label: this.name + ">" });
|
|
43914
|
+
this.text = spec.textContent ? spec.textContent.map((s) => ({ label: s, type: "text" })) : [];
|
|
43915
|
+
}
|
|
43916
|
+
}
|
|
43917
|
+
const Identifier$1 = /^[:\-\.\w\u00b7-\uffff]*$/;
|
|
43918
|
+
function attrCompletion(spec) {
|
|
43919
|
+
return Object.assign(Object.assign({ type: "property" }, spec.completion || {}), { label: spec.name });
|
|
43920
|
+
}
|
|
43921
|
+
function valueCompletion(spec) {
|
|
43922
|
+
return typeof spec == "string" ? { label: `"${spec}"`, type: "constant" } : /^"/.test(spec.label) ? spec : Object.assign(Object.assign({}, spec), { label: `"${spec.label}"` });
|
|
43923
|
+
}
|
|
43924
|
+
function completeFromSchema(eltSpecs, attrSpecs) {
|
|
43925
|
+
let allAttrs = [], globalAttrs = [];
|
|
43926
|
+
let attrValues = /* @__PURE__ */ Object.create(null);
|
|
43927
|
+
for (let s of attrSpecs) {
|
|
43928
|
+
let completion2 = attrCompletion(s);
|
|
43929
|
+
allAttrs.push(completion2);
|
|
43930
|
+
if (s.global)
|
|
43931
|
+
globalAttrs.push(completion2);
|
|
43932
|
+
if (s.values)
|
|
43933
|
+
attrValues[s.name] = s.values.map(valueCompletion);
|
|
43934
|
+
}
|
|
43935
|
+
let allElements = [], topElements = [];
|
|
43936
|
+
let byName = /* @__PURE__ */ Object.create(null);
|
|
43937
|
+
for (let s of eltSpecs) {
|
|
43938
|
+
let attrs = globalAttrs, attrVals = attrValues;
|
|
43939
|
+
if (s.attributes)
|
|
43940
|
+
attrs = attrs.concat(s.attributes.map((s2) => {
|
|
43941
|
+
if (typeof s2 == "string")
|
|
43942
|
+
return allAttrs.find((a) => a.label == s2) || { label: s2, type: "property" };
|
|
43943
|
+
if (s2.values) {
|
|
43944
|
+
if (attrVals == attrValues)
|
|
43945
|
+
attrVals = Object.create(attrVals);
|
|
43946
|
+
attrVals[s2.name] = s2.values.map(valueCompletion);
|
|
43947
|
+
}
|
|
43948
|
+
return attrCompletion(s2);
|
|
43949
|
+
}));
|
|
43950
|
+
let elt = new Element(s, attrs, attrVals);
|
|
43951
|
+
byName[elt.name] = elt;
|
|
43952
|
+
allElements.push(elt);
|
|
43953
|
+
if (s.top)
|
|
43954
|
+
topElements.push(elt);
|
|
43955
|
+
}
|
|
43956
|
+
if (!topElements.length)
|
|
43957
|
+
topElements = allElements;
|
|
43958
|
+
for (let i = 0; i < allElements.length; i++) {
|
|
43959
|
+
let s = eltSpecs[i], elt = allElements[i];
|
|
43960
|
+
if (s.children) {
|
|
43961
|
+
for (let ch of s.children)
|
|
43962
|
+
if (byName[ch])
|
|
43963
|
+
elt.children.push(byName[ch]);
|
|
43964
|
+
} else {
|
|
43965
|
+
elt.children = allElements;
|
|
43966
|
+
}
|
|
43967
|
+
}
|
|
43968
|
+
return (cx) => {
|
|
43969
|
+
var _a2;
|
|
43970
|
+
let { doc: doc2 } = cx.state, loc = findLocation(cx.state, cx.pos);
|
|
43971
|
+
if (!loc || loc.type == "tag" && !cx.explicit)
|
|
43972
|
+
return null;
|
|
43973
|
+
let { type: type2, from, context } = loc;
|
|
43974
|
+
if (type2 == "openTag") {
|
|
43975
|
+
let children = topElements;
|
|
43976
|
+
let parentName = elementName$1(doc2, context);
|
|
43977
|
+
if (parentName) {
|
|
43978
|
+
let parent = byName[parentName];
|
|
43979
|
+
children = (parent === null || parent === void 0 ? void 0 : parent.children) || allElements;
|
|
43980
|
+
}
|
|
43981
|
+
return {
|
|
43982
|
+
from,
|
|
43983
|
+
options: children.map((ch) => ch.completion),
|
|
43984
|
+
validFor: Identifier$1
|
|
43985
|
+
};
|
|
43986
|
+
} else if (type2 == "closeTag") {
|
|
43987
|
+
let parentName = elementName$1(doc2, context);
|
|
43988
|
+
return parentName ? {
|
|
43989
|
+
from,
|
|
43990
|
+
to: cx.pos + (doc2.sliceString(cx.pos, cx.pos + 1) == ">" ? 1 : 0),
|
|
43991
|
+
options: [((_a2 = byName[parentName]) === null || _a2 === void 0 ? void 0 : _a2.closeNameCompletion) || { label: parentName + ">", type: "type" }],
|
|
43992
|
+
validFor: Identifier$1
|
|
43993
|
+
} : null;
|
|
43994
|
+
} else if (type2 == "attrName") {
|
|
43995
|
+
let parent = byName[tagName(doc2, context)];
|
|
43996
|
+
return {
|
|
43997
|
+
from,
|
|
43998
|
+
options: (parent === null || parent === void 0 ? void 0 : parent.attrs) || globalAttrs,
|
|
43999
|
+
validFor: Identifier$1
|
|
44000
|
+
};
|
|
44001
|
+
} else if (type2 == "attrValue") {
|
|
44002
|
+
let attr = attrName(doc2, context, from);
|
|
44003
|
+
if (!attr)
|
|
44004
|
+
return null;
|
|
44005
|
+
let parent = byName[tagName(doc2, context)];
|
|
44006
|
+
let values = ((parent === null || parent === void 0 ? void 0 : parent.attrValues) || attrValues)[attr];
|
|
44007
|
+
if (!values || !values.length)
|
|
44008
|
+
return null;
|
|
44009
|
+
return {
|
|
44010
|
+
from,
|
|
44011
|
+
to: cx.pos + (doc2.sliceString(cx.pos, cx.pos + 1) == '"' ? 1 : 0),
|
|
44012
|
+
options: values,
|
|
44013
|
+
validFor: /^"[^"]*"?$/
|
|
44014
|
+
};
|
|
44015
|
+
} else if (type2 == "tag") {
|
|
44016
|
+
let parentName = elementName$1(doc2, context), parent = byName[parentName];
|
|
44017
|
+
let closing2 = [], last = context && context.lastChild;
|
|
44018
|
+
if (parentName && (!last || last.name != "CloseTag" || tagName(doc2, last) != parentName))
|
|
44019
|
+
closing2.push(parent ? parent.closeCompletion : { label: "</" + parentName + ">", type: "type", boost: 2 });
|
|
44020
|
+
let options = closing2.concat(((parent === null || parent === void 0 ? void 0 : parent.children) || (context ? allElements : topElements)).map((e) => e.openCompletion));
|
|
44021
|
+
if (context && (parent === null || parent === void 0 ? void 0 : parent.text.length)) {
|
|
44022
|
+
let openTag = context.firstChild;
|
|
44023
|
+
if (openTag.to > cx.pos - 20 && !/\S/.test(cx.state.sliceDoc(openTag.to, cx.pos)))
|
|
44024
|
+
options = options.concat(parent.text);
|
|
44025
|
+
}
|
|
44026
|
+
return {
|
|
44027
|
+
from,
|
|
44028
|
+
options,
|
|
44029
|
+
validFor: /^<\/?[:\-\.\w\u00b7-\uffff]*$/
|
|
44030
|
+
};
|
|
44031
|
+
} else {
|
|
44032
|
+
return null;
|
|
44033
|
+
}
|
|
44034
|
+
};
|
|
44035
|
+
}
|
|
44036
|
+
const xmlLanguage = /* @__PURE__ */ LRLanguage.define({
|
|
44037
|
+
name: "xml",
|
|
44038
|
+
parser: /* @__PURE__ */ parser$2.configure({
|
|
44039
|
+
props: [
|
|
44040
|
+
/* @__PURE__ */ indentNodeProp.add({
|
|
44041
|
+
Element(context) {
|
|
44042
|
+
let closed = /^\s*<\//.test(context.textAfter);
|
|
44043
|
+
return context.lineIndent(context.node.from) + (closed ? 0 : context.unit);
|
|
44044
|
+
},
|
|
44045
|
+
"OpenTag CloseTag SelfClosingTag"(context) {
|
|
44046
|
+
return context.column(context.node.from) + context.unit;
|
|
44047
|
+
}
|
|
44048
|
+
}),
|
|
44049
|
+
/* @__PURE__ */ foldNodeProp.add({
|
|
44050
|
+
Element(subtree) {
|
|
44051
|
+
let first = subtree.firstChild, last = subtree.lastChild;
|
|
44052
|
+
if (!first || first.name != "OpenTag")
|
|
44053
|
+
return null;
|
|
44054
|
+
return { from: first.to, to: last.name == "CloseTag" ? last.from : subtree.to };
|
|
44055
|
+
}
|
|
44056
|
+
}),
|
|
44057
|
+
/* @__PURE__ */ bracketMatchingHandle.add({
|
|
44058
|
+
"OpenTag CloseTag": (node) => node.getChild("TagName")
|
|
44059
|
+
})
|
|
44060
|
+
]
|
|
44061
|
+
}),
|
|
44062
|
+
languageData: {
|
|
44063
|
+
commentTokens: { block: { open: "<!--", close: "-->" } },
|
|
44064
|
+
indentOnInput: /^\s*<\/$/
|
|
44065
|
+
}
|
|
44066
|
+
});
|
|
44067
|
+
function xml(conf = {}) {
|
|
44068
|
+
let support = [xmlLanguage.data.of({
|
|
44069
|
+
autocomplete: completeFromSchema(conf.elements || [], conf.attributes || [])
|
|
44070
|
+
})];
|
|
44071
|
+
if (conf.autoCloseTags !== false)
|
|
44072
|
+
support.push(autoCloseTags$1);
|
|
44073
|
+
return new LanguageSupport(xmlLanguage, support);
|
|
44074
|
+
}
|
|
44075
|
+
function elementName$2(doc2, tree, max = doc2.length) {
|
|
44076
|
+
if (!tree)
|
|
44077
|
+
return "";
|
|
44078
|
+
let tag = tree.firstChild;
|
|
44079
|
+
let name2 = tag && tag.getChild("TagName");
|
|
44080
|
+
return name2 ? doc2.sliceString(name2.from, Math.min(name2.to, max)) : "";
|
|
44081
|
+
}
|
|
44082
|
+
const autoCloseTags$1 = /* @__PURE__ */ EditorView.inputHandler.of((view, from, to, text, insertTransaction) => {
|
|
44083
|
+
if (view.composing || view.state.readOnly || from != to || text != ">" && text != "/" || !xmlLanguage.isActiveAt(view.state, from, -1))
|
|
44084
|
+
return false;
|
|
44085
|
+
let base2 = insertTransaction(), { state } = base2;
|
|
44086
|
+
let closeTags = state.changeByRange((range) => {
|
|
44087
|
+
var _a2, _b, _c;
|
|
44088
|
+
let { head } = range;
|
|
44089
|
+
let didType = state.doc.sliceString(head - 1, head) == text;
|
|
44090
|
+
let after = syntaxTree(state).resolveInner(head, -1), name2;
|
|
44091
|
+
if (didType && text == ">" && after.name == "EndTag") {
|
|
44092
|
+
let tag = after.parent;
|
|
44093
|
+
if (((_b = (_a2 = tag.parent) === null || _a2 === void 0 ? void 0 : _a2.lastChild) === null || _b === void 0 ? void 0 : _b.name) != "CloseTag" && (name2 = elementName$2(state.doc, tag.parent, head))) {
|
|
44094
|
+
let to2 = head + (state.doc.sliceString(head, head + 1) === ">" ? 1 : 0);
|
|
44095
|
+
let insert2 = `</${name2}>`;
|
|
44096
|
+
return { range, changes: { from: head, to: to2, insert: insert2 } };
|
|
44097
|
+
}
|
|
44098
|
+
} else if (didType && text == "/" && after.name == "StartCloseTag") {
|
|
44099
|
+
let base3 = after.parent;
|
|
44100
|
+
if (after.from == head - 2 && ((_c = base3.lastChild) === null || _c === void 0 ? void 0 : _c.name) != "CloseTag" && (name2 = elementName$2(state.doc, base3, head))) {
|
|
44101
|
+
let to2 = head + (state.doc.sliceString(head, head + 1) === ">" ? 1 : 0);
|
|
44102
|
+
let insert2 = `${name2}>`;
|
|
44103
|
+
return {
|
|
44104
|
+
range: EditorSelection.cursor(head + insert2.length, -1),
|
|
44105
|
+
changes: { from: head, to: to2, insert: insert2 }
|
|
44106
|
+
};
|
|
44107
|
+
}
|
|
44108
|
+
}
|
|
44109
|
+
return { range };
|
|
44110
|
+
});
|
|
44111
|
+
if (closeTags.changes.empty)
|
|
44112
|
+
return false;
|
|
44113
|
+
view.dispatch([
|
|
44114
|
+
base2,
|
|
44115
|
+
state.update(closeTags, {
|
|
44116
|
+
userEvent: "input.complete",
|
|
44117
|
+
scrollIntoView: true
|
|
44118
|
+
})
|
|
44119
|
+
]);
|
|
44120
|
+
return true;
|
|
44121
|
+
});
|
|
44122
|
+
const commentKeymap = keymap.of([
|
|
44123
|
+
{ key: "Mod-/", run: toggleComment, preventDefault: true }
|
|
44124
|
+
]);
|
|
44125
|
+
function jsonWithComments() {
|
|
44126
|
+
const lang = json();
|
|
44127
|
+
return [lang, lang.language.data.of({ commentTokens: { line: "//" } }), commentKeymap];
|
|
44128
|
+
}
|
|
44129
|
+
function xmlWithComments() {
|
|
44130
|
+
return [xml(), commentKeymap];
|
|
44131
|
+
}
|
|
42954
44132
|
function devAssert(condition, message) {
|
|
42955
44133
|
const booleanCondition = Boolean(condition);
|
|
42956
44134
|
if (!booleanCondition) {
|
|
@@ -54542,7 +55720,7 @@ const stateExtensions = (schema, opts) => [
|
|
|
54542
55720
|
optionsStateField.init(() => Object.assign(Object.assign({}, defaultOpts), opts))
|
|
54543
55721
|
];
|
|
54544
55722
|
const spec_name = { __proto__: null, query: 241, mutation: 243, subscription: 245, on: 86, fragment: 92, schema: 102, scalar: 114, type: 120, implements: 126, interface: 140, union: 146, enum: 154, input: 164, directive: 172, repeatable: 176, extend: 192 };
|
|
54545
|
-
const parser$
|
|
55723
|
+
const parser$1 = /* @__PURE__ */ LRParser.deserialize({
|
|
54546
55724
|
version: 14,
|
|
54547
55725
|
states: "LWOYQPOOO!WQPO'#C}O!`QPO'#C_OOQO'#C_'#C_O!iQPO'#DYOOQO'#Ev'#EvOOQO'#D_'#D_O!nQPO'#D^O#_QPO'#D^O!iQPO'#DhO!iQPO'#DrO!iQPO'#DuO!iQPO'#DyO!iQPO'#EOOOQO'#Dd'#DdO#fQPO'#ESOOQO'#D]'#D]O!vQPO'#E^OOQO'#Ea'#EaOOQO'#E]'#E]OOQO'#FT'#FTOOQO'#Eu'#EuOOQO'#Eh'#EhQYQPOOOOQO'#C`'#C`OOQO'#DZ'#DZOOQO'#D`'#D`OOQO'#Di'#DiOOQO'#Ds'#DsOOQO'#Dv'#DvOOQO'#Dz'#DzOOQO'#EP'#EPOOQO'#ET'#ETOOQO'#E_'#E_O#kQPO'#CaO$VQPO'#DQO$[QPO'#DPO$sQPO'#DPO$xQPO'#DSO%WQPO'#DOOOQO'#En'#EnO%fQPO,59iOOQO'#Ca'#CaO%qQPO'#CxOOQO'#El'#ElO'hQPO'#CwO)[QPO'#CdOOQO,58y,58yO)aQPO,58yO)fQPO,58yO)nQPO,58yOOQO'#DT'#DTO)yQPO,59tO{QPO'#FUOOQO'#Db'#DbOOQO,59x,59xO*OQPO,59xO!nQPO,59xO!iQPO,5:PO!iQPO,5:SO!iQPO,5:^O!iQPO,5:aO!iQPO,5:eO!iQPO,5:jO*TQPO,5:nOOQO'#Df'#DfO*YQPO,5:SO+aQPO,5:^O,hQPO,5:aO-oQPO,5:eO.sQPO,5:jO/wQPO,5:nO!nQPO,5:xO!iQPO,5:|O!iQPO,5:}O!iQPO,5;OO!iQPO,5;PO!iQPO,5;QO!iQPO,5;ROOQO-E8f-E8fOOQO,59l,59lO0VQPO'#CzOOQO,59k,59kO0[QPO,59kO0mQPO,59kOOQO'#DR'#DRO0tQPO,59kO1OQPO,59nO!iQPO'#DVOOQO,59p,59pO)aQPO,59pO)fQPO,59pOOQO'#DW'#DWOOQO,59j,59jOOQO-E8l-E8lOOQO1G/T1G/TOOQO,59d,59dOOQO-E8j-E8jO1aQPO'#CeOOQO'#Ei'#EiO1fQPO,59OOOQO1G.e1G.eO)aQPO1G.eO)fQPO1G.eO)fQPO1G/`O1nQPO'#DcO1sQPO,5;pOOQO1G/d1G/dO*OQPO1G/dO1xQPO1G/kO4QQPO1G/nO5]QPO1G/xO6hQPO1G/{O7pQPO1G0PO8xQPO1G0UO/wQPO1G0YO9PQPO1G/nO9WQPO'#DkO9`QPO'#FWOOQO'#Dn'#DnOOQO1G/n1G/nO9hQPO1G/nOOQO'#Dl'#DlO:iQPO1G/xOOQO1G/x1G/xO:pQPO1G/xO;qQPO1G/{O;xQPO'#DxO5dQPO1G/{O<QQQO'#FYOOQO'#D|'#D|OOQO1G0P1G0PO6oQPO1G0PO9`QPO'#FZOOQO'#ER'#EROOQO1G0U1G0UO7wQPO1G0UO<YQPO'#DqO!iQPO'#DqOOQO'#Ep'#EpO<_QPO'#DpO<pQSO1G0YO)yQPO1G0YO>QQPO1G0YOOQO'#EV'#EVOOQO1G0d1G0dO>YQPO1G0dO!qQPO1G0hO?ZQPO1G0iO?ZQPO1G0jO?fQPO1G0kO?nQPO1G0lO?vQPO1G0mOOQO'#C|'#C|O@OQPO'#C{OOQO'#Em'#EmO@TQPO,59fOOQO1G/V1G/VO@]QPO1G/VO@nQPO1G/VOOQO1G/Y1G/YOOQO'#Cg'#CgOOQO,59q,59qOOQO1G/[1G/[O)aQPO1G/[O@uQPO,59POOQO-E8g-E8gOOQO1G.j1G.jOOQO7+$P7+$PO)aQPO7+$POOQO7+$z7+$zO)aQPO7+$zO!iQPO,59}OOQO1G1[1G1[OOQO7+%O7+%OOOQO7+%V7+%VOBOQPO7+%YOOQO7+%Y7+%YO@}QPO7+%YOCZQPO7+%dOOQO7+%d7+%dOBYQPO7+%dODfQPO7+%gODmQPO7+%gOOQO7+%k7+%kODtQPO7+%kOOQO7+%p7+%pOEuQPO7+%pO<pQSO7+%tO)yQPO7+%tO>QQPO7+%tO!iQPO,5:VOOQO,5:V,5:VOFvQPO'#DoO!iQPO'#DoOOQO'#Eo'#EoOGRQPO,5;rO!iQPO,5:dOOQO,5:d,5:dOG^QQO'#D}OGlQQO'#D}OOQO'#Eq'#EqOGqQQO,5;tOG|QPO,5;uO@uQPO,5:]OHXQPO,5:]OOQO-E8n-E8nOOQO'#EZ'#EZOOQO'#E['#E[OOQO'#EY'#EYOH^QPO7+%tOOQO'#EX'#EXO<sQSO'#EXOOQO7+&O7+&OOOQO7+&S7+&SOJcQPO7+&TOOQO7+&T7+&TOIbQPO7+&TOKnQPO7+&UOOQO7+&U7+&UOJmQPO7+&UOLyQPO7+&VOMQQPO7+&VOOQO7+&W7+&WOMXQPO7+&WOOQO7+&X7+&XONYQPO7+&XO! ZQQO,59gOOQO-E8k-E8kOOQO1G/Q1G/QOOQO7+$q7+$qO! xQPO7+$qOOQO7+$v7+$vO@uQPO'#CjO!!ZQPO'#E|OOQO'#E|'#E|O!#UQPO1G.kOOQO<<Gk<<GkOOQO<<Hf<<HfOOQO1G/i1G/iOOQO<<Ht<<HtO!#gQPO<<HtOOQO<<IO<<IOO!$hQPO<<IOO!%iQPO<<IROOQO<<IV<<IVOOQO<<I[<<I[O!&mQPO<<I`O<pQSO<<I`O)yQPO<<I`OOQO1G/q1G/qO@uQPO,5:ZO!'qQPO,5:ZO!'vQPO,5:ZOOQO-E8m-E8mOOQO1G1^1G1^OOQO1G0O1G0OO!(RQQO'#CxO!(dQQO'#CwOOQO,5:i,5:iO!(rQQO,5:iOOQO-E8o-E8oOOQO1G1`1G1`OOQO1G1a1G1aO!)QQPO1G/wO@uQPO1G/wO<sQSO,5:sOOQO,5:s,5:sOOQO<<Io<<IoO!)lQPO<<IoOOQO<<Ip<<IpO!*mQPO<<IpO!+nQPO<<IqOOQO<<Ir<<IrOOQO<<Is<<IsO!,rQQO'#CsO!,yQPO'#CvOOQO'#FP'#FPO!-RQPO1G/ROOQO<<H]<<H]O!-^QPO,59UOOQO,59V,59VO! ZQQO'#ClOOQO7+$V7+$VO!-cQPO7+$VO!-nQPO7+$VOOQOAN>`AN>`OOQOAN>jAN>jO!-|QPOAN>zO<pQSOAN>zO!/QQPO1G/uO@uQPO1G/uO!/`QPO1G/uOOQO1G0T1G0TOOQO7+%c7+%cO!/eQPO7+%cO!/|QPO7+%cOOQO1G0_1G0_OOQOAN?ZAN?ZOOQOAN?[AN?[O!0TQQO'#EjO!0xQQO,59_OOQO,59_,59_O!1PQPO'#FROOQO'#Ek'#EkO!1UQPO,59bOOQO,59b,59bOOQO7+$m7+$mOOQO1G.p1G.pOOQO,59W,59WOOQO<<Gq<<GqO!1^QPO<<GqO!1iQPOG24fOOQO7+%a7+%aO!2mQPO7+%aO@uQPO7+%aOOQO<<H}<<H}O!2{QPO<<H}OOQO,5;U,5;UOOQO-E8h-E8hOOQO1G.y1G.yO! ZQQO,5;mOOQO-E8i-E8iOOQO1G.|1G.|OOQOAN=]AN=]OOQO<<H{<<H{O!3dQPO<<H{OOQOAN>iAN>iO!3rQPO1G1XOOQOAN>gAN>gOOQO7+&s7+&s",
|
|
54548
55726
|
stateData: "!4S~O#hOSPOS~OcUOiPO!OiO!TjO!^kO!hlO!kmO!onO!toO!xpO#SqO#lhO#mhO#nhO~O#krO#vvO~OV!OOiPOm{O#kzO~Oi!VOm{O~O!TjO!Z!cO!^kO!hlO!kmO!onO!toO~O!xpO~P!vOm!iO~OVuXhuXiuXmuX#kuX#oTX#tuX#vuX~O#o!rO~OV!sOiPOm{OhsX#ksX#tsX#vsX~O#k!wO~OiPOm{O{#OO#kzO~O#t#POhrX#krX#vrX~Oh#RO#krO#vvO~OV!sOilXmlXhlX#klX#tlX#vlXclX!OlX!TlX!^lX!hlX!klX!olX!tlX!xlX#SlX#flX#llX#mlX#nlX#rlXUlXYlX{lX!zlX#olX~Om{OikXhkX#kkX#tkX#vkXckX!OkX!TkX!^kX!hkX!kkX!okX!tkX!xkX#SkX#fkX#lkX#mkX#nkX#rkXUkXYkX{kX!zkX#okX~OY#UO~OiPO~OiPOm{O~OV!OOiPOm{O~O{#OO~Oi!VO~Om#gO~Oi#jOm{O!a#nOc![a!O![a!T![a!^![a!h![a!k![a!o![a!t![a!x![a#S![a#f![a#l![a#m![a#n![a~Oi#jOm{O!a#nOc!fa!O!fa!T!fa!^!fa!h!fa!k!fa!o!fa!t!fa!x!fa#S!fa#f!fa#l!fa#m!fa#n!fa~Om{O#r#sOc!iai!ia!O!ia!T!ia!^!ia!h!ia!k!ia!o!ia!t!ia!x!ia#S!ia#f!ia#l!ia#m!ia#n!ia~Oi#uOm{Oc!ma!O!ma!T!ma!^!ma!h!ma!k!ma!o!ma!t!ma!x!ma#S!ma#f!ma#l!ma#m!ma#n!ma~Oi#yOm{Oc!ra!O!ra!T!ra!^!ra!h!ra!k!ra!o!ra!t!ra!x!ra#S!ra#f!ra#l!ra#m!ra#n!ra~OcUO{#OO!z$UO#kzO~O#k$_O~OiPOhsa#ksa#tsa#vsa~Om{O~P0[OV!sOm{O~P0[Om{Ohva#kva#tva#vva~O#o$kO~OU$mOY#UO~O#o$rO~Oh$sO~Om{Oc!Xii!Xi!O!Xi!T!Xi!^!Xi!h!Xi!k!Xi!o!Xi!t!Xi!x!Xi#S!Xi#f!Xi#l!Xi#m!Xi#n!Xi~Oi#jOm{Oc![i!O![i!T![i!^![i!h![i!k![i!o![i!t![i!x![i#S![i#f![i#l![i#m![i#n![i~O!a#nO~P2|Oi#jOm{Oc!fi!O!fi!T!fi!^!fi!h!fi!k!fi!o!fi!t!fi!x!fi#S!fi#f!fi#l!fi#m!fi#n!fi~O!a#nO~P4XO#r#sOc!iii!ii!O!ii!T!ii!^!ii!h!ii!k!ii!o!ii!t!ii!x!ii#S!ii#f!ii#l!ii#m!ii#n!ii~Om{O~P5dOi#uOc!mi!O!mi!T!mi!^!mi!h!mi!k!mi!o!mi!t!mi!x!mi#S!mi#f!mi#l!mi#m!mi#n!mi~Om{O~P6oOi#yOc!ri!O!ri!T!ri!^!ri!h!ri!k!ri!o!ri!t!ri!x!ri#S!ri#f!ri#l!ri#m!ri#n!ri~Om{O~P7wO#y%VO~P2|O#kzO#y%VO~OcUO#kzO~Oi#jOc![i!O![i!T![i!^![i!h![i!k![i!o![i!t![i!x![i#S![i#f![i#l![i#m![i#n![i~O#y%VO~P4XOi#jOc!fi!O!fi!T!fi!^!fi!h!fi!k!fi!o!fi!t!fi!x!fi#S!fi#f!fi#l!fi#m!fi#n!fi~O#{%]O~P5gO#kzO#{%]O~OcUOf%_O~O#o%dO~OcUO#kzO{!dX!z!dX#o!dX~O#{%lO$O%gO$P%gO$Q%gO$R%gO$S%gO$T%gO$U%gO$V%gO$W%hO$X%hO$Y%hO$Z%hO$[%hO$]%hO$^%hO$_%hO$`%hO$a%hO$b%hO~O{#OO!z$UO~Oi!VOc#Qi!O#Qi!T#Qi!^#Qi!h#Qi!k#Qi!o#Qi!t#Qi!x#Qi#S#Qi#f#Qi#l#Qi#m#Qi#n#Qi~Oi#jOm{O!a#nO~Om{O#r#sO~Oi#uOm{O~Oi#yOm{O~O#o%{O~OU%}O#k$_O~OiPOhsi#ksi#tsi#vsi~Om{O~P@]O]&RO#kzO~Oi#jOc![q!O![q!T![q!^![q!h![q!k![q!o![q!t![q!x![q#S![q#f![q#l![q#m![q#n![q~Om{O#y%VO~P@}Oi#jOc!fq!O!fq!T!fq!^!fq!h!fq!k!fq!o!fq!t!fq!x!fq#S!fq#f!fq#l!fq#m!fq#n!fq~Om{O#y%VO~PBYOc!iqi!iq!O!iq!T!iq!^!iq!h!iq!k!iq!o!iq!t!iq!x!iq#S!iq#f!iq#l!iq#m!iq#n!iq~O#{%]O~PCeO#r#sO~PCeOi#uOc!mq!O!mq!T!mq!^!mq!h!mq!k!mq!o!mq!t!mq!x!mq#S!mq#f!mq#l!mq#m!mq#n!mq~Oi#yOc!rq!O!rq!T!rq!^!rq!h!rq!k!rq!o!rq!t!rq!x!rq#S!rq#f!rq#l!rq#m!rq#n!rq~OcUO#kzO#o&eO~OcUOh&iO#kzO~Om&kOc!qXf!qXh!qX~Of&nO~OcUOf%_Oh&pO~OcUOh&qO#kzO~O#o&sO~O#{&tOc!vqi!vq!O!vq!T!vq!^!vq!h!vq!k!vq!o!vq!t!vq!x!vq#S!vq#f!vq#l!vq#m!vq#n!vq~Oi#jOc#Vq!O#Vq!T#Vq!^#Vq!h#Vq!k#Vq!o#Vq!t#Vq!x#Vq#S#Vq#f#Vq#l#Vq#m#Vq#n#Vq~Om{O#y%VO~PIbOi#jOc#Wq!O#Wq!T#Wq!^#Wq!h#Wq!k#Wq!o#Wq!t#Wq!x#Wq#S#Wq#f#Wq#l#Wq#m#Wq#n#Wq~Om{O#y%VO~PJmOc#Xqi#Xq!O#Xq!T#Xq!^#Xq!h#Xq!k#Xq!o#Xq!t#Xq!x#Xq#S#Xq#f#Xq#l#Xq#m#Xq#n#Xq~O#{%]O~PKxO#r#sO~PKxOi#uOc#Yq!O#Yq!T#Yq!^#Yq!h#Yq!k#Yq!o#Yq!t#Yq!x#Yq#S#Yq#f#Yq#l#Yq#m#Yq#n#Yq~Oi#yOc#Zq!O#Zq!T#Zq!^#Zq!h#Zq!k#Zq!o#Zq!t#Zq!x#Zq#S#Zq#f#Zq#l#Zq#m#Zq#n#Zq~OY'PO]&}Oa'POb'POc'POd'POe'POf'POi'OO~OiPOhsq#ksq#tsq#vsq~O#q'TOU#pXY#pXm#pX#r#pX#t#pXc#pX{#pX!z#pX#k#pX[#pXh#pX#o#pX~Om{O#r'UO#t'VOUXiYXi~Oi#jOc![y!O![y!T![y!^![y!h![y!k![y!o![y!t![y!x![y#S![y#f![y#l![y#m![y#n![y~Oi#jOc!fy!O!fy!T!fy!^!fy!h!fy!k!fy!o!fy!t!fy!x!fy#S!fy#f!fy#l!fy#m!fy#n!fy~O#{%]Oc!iyi!iy!O!iy!T!iy!^!iy!h!iy!k!iy!o!iy!t!iy!x!iy#S!iy#f!iy#l!iy#m!iy#n!iy~O#{&tOc!vyi!vy!O!vy!T!vy!^!vy!h!vy!k!vy!o!vy!t!vy!x!vy#S!vy#f!vy#l!vy#m!vy#n!vy~O#o'_O~OcUO#kzO#o'_O~OV!sOclXflXhlXmlX~Om&kOckXfkXhkX~Om&kOc!qaf!qah!qa~Om{O#r'UOc!ei{!ei!z!ei#k!eih!ei#o!ei~Oi#jOc#Vy!O#Vy!T#Vy!^#Vy!h#Vy!k#Vy!o#Vy!t#Vy!x#Vy#S#Vy#f#Vy#l#Vy#m#Vy#n#Vy~Oi#jOc#Wy!O#Wy!T#Wy!^#Wy!h#Wy!k#Wy!o#Wy!t#Wy!x#Wy#S#Wy#f#Wy#l#Wy#m#Wy#n#Wy~O#{%]Oc#Xyi#Xy!O#Xy!T#Xy!^#Xy!h#Xy!k#Xy!o#Xy!t#Xy!x#Xy#S#Xy#f#Xy#l#Xy#m#Xy#n#Xy~O['jO~P! ZOh'nO#kzO~O#t'oOUoi#koi~O['pO~O#t'rOUXqYXq~Om{O#t'rOUXqYXq~O#{&tOc!v!Ri!v!R!O!v!R!T!v!R!^!v!R!h!v!R!k!v!R!o!v!R!t!v!R!x!v!R#S!v!R#f!v!R#l!v!R#m!v!R#n!v!R~Om{Oc!cih!ci#k!ci~O#o'wO~Om{Oc!eq{!eq!z!eq#k!eqh!eq#o!eq~O#r'UO~P!/eO#t'zOY#^X[#^X]#^Xa#^Xb#^Xc#^Xd#^Xe#^Xf#^Xi#^X~O['|O~P! ZO#o'}O~Oh(PO#kzO~O#t(QOUXyYXy~O#{&tOc!v!Zi!v!Z!O!v!Z!T!v!Z!^!v!Z!h!v!Z!k!v!Z!o!v!Z!t!v!Z!x!v!Z#S!v!Z#f!v!Z#l!v!Z#m!v!Z#n!v!Z~Om{Oc!cqh!cq#k!cq~Om{Oc!ey{!ey!z!ey#k!eyh!ey#o!ey~Om{Oc!cyh!cy#k!cy~O#t(WOh#ui#k#ui~Odefe~",
|
|
@@ -54565,7 +55743,7 @@ const nodesWithBraces = "RootTypeDefinition InputFieldsDefinition EnumValuesDefi
|
|
|
54565
55743
|
const keywords$1 = "scalar type interface union enum input implements fragment extend schema directive on repeatable";
|
|
54566
55744
|
const punctuations = "( ) { } : [ ]";
|
|
54567
55745
|
const graphqlLanguage = /* @__PURE__ */ LRLanguage.define({
|
|
54568
|
-
parser: /* @__PURE__ */ parser$
|
|
55746
|
+
parser: /* @__PURE__ */ parser$1.configure({
|
|
54569
55747
|
props: [
|
|
54570
55748
|
/* @__PURE__ */ styleTags({
|
|
54571
55749
|
Variable: tags.variableName,
|
|
@@ -55259,383 +56437,6 @@ function GraphQLEditor({ request, onChange }) {
|
|
|
55259
56437
|
] })
|
|
55260
56438
|
] });
|
|
55261
56439
|
}
|
|
55262
|
-
const StartTag = 1, StartCloseTag = 2, MissingCloseTag = 3, mismatchedStartCloseTag = 4, incompleteStartCloseTag = 5, commentContent$1 = 36, piContent$1 = 37, cdataContent$1 = 38, Element$1 = 11, OpenTag = 13;
|
|
55263
|
-
function nameChar(ch) {
|
|
55264
|
-
return ch == 45 || ch == 46 || ch == 58 || ch >= 65 && ch <= 90 || ch == 95 || ch >= 97 && ch <= 122 || ch >= 161;
|
|
55265
|
-
}
|
|
55266
|
-
function isSpace(ch) {
|
|
55267
|
-
return ch == 9 || ch == 10 || ch == 13 || ch == 32;
|
|
55268
|
-
}
|
|
55269
|
-
let cachedName = null, cachedInput = null, cachedPos = 0;
|
|
55270
|
-
function tagNameAfter(input, offset) {
|
|
55271
|
-
let pos = input.pos + offset;
|
|
55272
|
-
if (cachedInput == input && cachedPos == pos) return cachedName;
|
|
55273
|
-
while (isSpace(input.peek(offset))) offset++;
|
|
55274
|
-
let name2 = "";
|
|
55275
|
-
for (; ; ) {
|
|
55276
|
-
let next = input.peek(offset);
|
|
55277
|
-
if (!nameChar(next)) break;
|
|
55278
|
-
name2 += String.fromCharCode(next);
|
|
55279
|
-
offset++;
|
|
55280
|
-
}
|
|
55281
|
-
cachedInput = input;
|
|
55282
|
-
cachedPos = pos;
|
|
55283
|
-
return cachedName = name2 || null;
|
|
55284
|
-
}
|
|
55285
|
-
function ElementContext(name2, parent) {
|
|
55286
|
-
this.name = name2;
|
|
55287
|
-
this.parent = parent;
|
|
55288
|
-
}
|
|
55289
|
-
const elementContext = new ContextTracker({
|
|
55290
|
-
start: null,
|
|
55291
|
-
shift(context, term, stack, input) {
|
|
55292
|
-
return term == StartTag ? new ElementContext(tagNameAfter(input, 1) || "", context) : context;
|
|
55293
|
-
},
|
|
55294
|
-
reduce(context, term) {
|
|
55295
|
-
return term == Element$1 && context ? context.parent : context;
|
|
55296
|
-
},
|
|
55297
|
-
reuse(context, node, _stack, input) {
|
|
55298
|
-
let type2 = node.type.id;
|
|
55299
|
-
return type2 == StartTag || type2 == OpenTag ? new ElementContext(tagNameAfter(input, 1) || "", context) : context;
|
|
55300
|
-
},
|
|
55301
|
-
strict: false
|
|
55302
|
-
});
|
|
55303
|
-
const startTag = new ExternalTokenizer((input, stack) => {
|
|
55304
|
-
if (input.next != 60) return;
|
|
55305
|
-
input.advance();
|
|
55306
|
-
if (input.next == 47) {
|
|
55307
|
-
input.advance();
|
|
55308
|
-
let name2 = tagNameAfter(input, 0);
|
|
55309
|
-
if (!name2) return input.acceptToken(incompleteStartCloseTag);
|
|
55310
|
-
if (stack.context && name2 == stack.context.name) return input.acceptToken(StartCloseTag);
|
|
55311
|
-
for (let cx = stack.context; cx; cx = cx.parent) if (cx.name == name2) return input.acceptToken(MissingCloseTag, -2);
|
|
55312
|
-
input.acceptToken(mismatchedStartCloseTag);
|
|
55313
|
-
} else if (input.next != 33 && input.next != 63) {
|
|
55314
|
-
return input.acceptToken(StartTag);
|
|
55315
|
-
}
|
|
55316
|
-
}, { contextual: true });
|
|
55317
|
-
function scanTo(type2, end) {
|
|
55318
|
-
return new ExternalTokenizer((input) => {
|
|
55319
|
-
let len = 0, first = end.charCodeAt(0);
|
|
55320
|
-
scan: for (; ; input.advance(), len++) {
|
|
55321
|
-
if (input.next < 0) break;
|
|
55322
|
-
if (input.next == first) {
|
|
55323
|
-
for (let i = 1; i < end.length; i++)
|
|
55324
|
-
if (input.peek(i) != end.charCodeAt(i)) continue scan;
|
|
55325
|
-
break;
|
|
55326
|
-
}
|
|
55327
|
-
}
|
|
55328
|
-
if (len) input.acceptToken(type2);
|
|
55329
|
-
});
|
|
55330
|
-
}
|
|
55331
|
-
const commentContent = scanTo(commentContent$1, "-->");
|
|
55332
|
-
const piContent = scanTo(piContent$1, "?>");
|
|
55333
|
-
const cdataContent = scanTo(cdataContent$1, "]]>");
|
|
55334
|
-
const xmlHighlighting = styleTags({
|
|
55335
|
-
Text: tags.content,
|
|
55336
|
-
"StartTag StartCloseTag EndTag SelfCloseEndTag": tags.angleBracket,
|
|
55337
|
-
TagName: tags.tagName,
|
|
55338
|
-
"MismatchedCloseTag/TagName": [tags.tagName, tags.invalid],
|
|
55339
|
-
AttributeName: tags.attributeName,
|
|
55340
|
-
AttributeValue: tags.attributeValue,
|
|
55341
|
-
Is: tags.definitionOperator,
|
|
55342
|
-
"EntityReference CharacterReference": tags.character,
|
|
55343
|
-
Comment: tags.blockComment,
|
|
55344
|
-
ProcessingInst: tags.processingInstruction,
|
|
55345
|
-
DoctypeDecl: tags.documentMeta,
|
|
55346
|
-
Cdata: tags.special(tags.string)
|
|
55347
|
-
});
|
|
55348
|
-
const parser$1 = LRParser.deserialize({
|
|
55349
|
-
version: 14,
|
|
55350
|
-
states: ",lOQOaOOOrOxO'#CfOzOpO'#CiO!tOaO'#CgOOOP'#Cg'#CgO!{OrO'#CrO#TOtO'#CsO#]OpO'#CtOOOP'#DT'#DTOOOP'#Cv'#CvQQOaOOOOOW'#Cw'#CwO#eOxO,59QOOOP,59Q,59QOOOO'#Cx'#CxO#mOpO,59TO#uO!bO,59TOOOP'#C|'#C|O$TOaO,59RO$[OpO'#CoOOOP,59R,59ROOOQ'#C}'#C}O$dOrO,59^OOOP,59^,59^OOOS'#DO'#DOO$lOtO,59_OOOP,59_,59_O$tOpO,59`O$|OpO,59`OOOP-E6t-E6tOOOW-E6u-E6uOOOP1G.l1G.lOOOO-E6v-E6vO%UO!bO1G.oO%UO!bO1G.oO%dOpO'#CkO%lO!bO'#CyO%zO!bO1G.oOOOP1G.o1G.oOOOP1G.w1G.wOOOP-E6z-E6zOOOP1G.m1G.mO&VOpO,59ZO&_OpO,59ZOOOQ-E6{-E6{OOOP1G.x1G.xOOOS-E6|-E6|OOOP1G.y1G.yO&gOpO1G.zO&gOpO1G.zOOOP1G.z1G.zO&oO!bO7+$ZO&}O!bO7+$ZOOOP7+$Z7+$ZOOOP7+$c7+$cO'YOpO,59VO'bOpO,59VO'mO!bO,59eOOOO-E6w-E6wO'{OpO1G.uO'{OpO1G.uOOOP1G.u1G.uO(TOpO7+$fOOOP7+$f7+$fO(]O!bO<<GuOOOP<<Gu<<GuOOOP<<G}<<G}O'bOpO1G.qO'bOpO1G.qO(hO#tO'#CnO(vO&jO'#CnOOOO1G.q1G.qO)UOpO7+$aOOOP7+$a7+$aOOOP<<HQ<<HQOOOPAN=aAN=aOOOPAN=iAN=iO'bOpO7+$]OOOO7+$]7+$]OOOO'#Cz'#CzO)^O#tO,59YOOOO,59Y,59YOOOO'#C{'#C{O)lO&jO,59YOOOP<<G{<<G{OOOO<<Gw<<GwOOOO-E6x-E6xOOOO1G.t1G.tOOOO-E6y-E6y",
|
|
55351
|
-
stateData: ")z~OPQOSVOTWOVWOWWOXWOiXOyPO!QTO!SUO~OvZOx]O~O^`Oz^O~OPQOQcOSVOTWOVWOWWOXWOyPO!QTO!SUO~ORdO~P!SOteO!PgO~OuhO!RjO~O^lOz^O~OvZOxoO~O^qOz^O~O[vO`sOdwOz^O~ORyO~P!SO^{Oz^O~OteO!P}O~OuhO!R!PO~O^!QOz^O~O[!SOz^O~O[!VO`sOd!WOz^O~Oa!YOz^O~Oz^O[mX`mXdmX~O[!VO`sOd!WO~O^!]Oz^O~O[!_Oz^O~O[!aOz^O~O[!cO`sOd!dOz^O~O[!cO`sOd!dO~Oa!eOz^O~Oz^O{!gO}!hO~Oz^O[ma`madma~O[!kOz^O~O[!lOz^O~O[!mO`sOd!nO~OW!qOX!qO{!sO|!qO~OW!tOX!tO}!sO!O!tO~O[!vOz^O~OW!qOX!qO{!yO|!qO~OW!tOX!tO}!yO!O!tO~O",
|
|
55352
|
-
goto: "%cxPPPPPPPPPPyyP!PP!VPP!`!jP!pyyyP!v!|#S$[$k$q$w$}%TPPPP%ZXWORYbXRORYb_t`qru!T!U!bQ!i!YS!p!e!fR!w!oQdRRybXSORYbQYORmYQ[PRn[Q_QQkVjp_krz!R!T!X!Z!^!`!f!j!oQr`QzcQ!RlQ!TqQ!XsQ!ZtQ!^{Q!`!QQ!f!YQ!j!]R!o!eQu`S!UqrU![u!U!bR!b!TQ!r!gR!x!rQ!u!hR!z!uQbRRxbQfTR|fQiUR!OiSXOYTaRb",
|
|
55353
|
-
nodeNames: "⚠ StartTag StartCloseTag MissingCloseTag StartCloseTag StartCloseTag Document Text EntityReference CharacterReference Cdata Element EndTag OpenTag TagName Attribute AttributeName Is AttributeValue CloseTag SelfCloseEndTag SelfClosingTag Comment ProcessingInst MismatchedCloseTag DoctypeDecl",
|
|
55354
|
-
maxTerm: 50,
|
|
55355
|
-
context: elementContext,
|
|
55356
|
-
nodeProps: [
|
|
55357
|
-
["closedBy", 1, "SelfCloseEndTag EndTag", 13, "CloseTag MissingCloseTag"],
|
|
55358
|
-
["openedBy", 12, "StartTag StartCloseTag", 19, "OpenTag", 20, "StartTag"],
|
|
55359
|
-
["isolate", -6, 13, 18, 19, 21, 22, 24, ""]
|
|
55360
|
-
],
|
|
55361
|
-
propSources: [xmlHighlighting],
|
|
55362
|
-
skippedNodes: [0],
|
|
55363
|
-
repeatNodeCount: 9,
|
|
55364
|
-
tokenData: "!)v~R!YOX$qXY)iYZ)iZ]$q]^)i^p$qpq)iqr$qrs*vsv$qvw+fwx/ix}$q}!O0[!O!P$q!P!Q2z!Q![$q![!]4n!]!^$q!^!_8U!_!`!#t!`!a!$l!a!b!%d!b!c$q!c!}4n!}#P$q#P#Q!'W#Q#R$q#R#S4n#S#T$q#T#o4n#o%W$q%W%o4n%o%p$q%p&a4n&a&b$q&b1p4n1p4U$q4U4d4n4d4e$q4e$IS4n$IS$I`$q$I`$Ib4n$Ib$Kh$q$Kh%#t4n%#t&/x$q&/x&Et4n&Et&FV$q&FV;'S4n;'S;:j8O;:j;=`)c<%l?&r$q?&r?Ah4n?Ah?BY$q?BY?Mn4n?MnO$qi$zXVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qa%nVVP!O`Ov%gwx&Tx!^%g!^!_&o!_;'S%g;'S;=`'W<%lO%gP&YTVPOv&Tw!^&T!_;'S&T;'S;=`&i<%lO&TP&lP;=`<%l&T`&tS!O`Ov&ox;'S&o;'S;=`'Q<%lO&o`'TP;=`<%l&oa'ZP;=`<%l%gX'eWVP|WOr'^rs&Tsv'^w!^'^!^!_'}!_;'S'^;'S;=`(i<%lO'^W(ST|WOr'}sv'}w;'S'};'S;=`(c<%lO'}W(fP;=`<%l'}X(lP;=`<%l'^h(vV|W!O`Or(ors&osv(owx'}x;'S(o;'S;=`)]<%lO(oh)`P;=`<%l(oi)fP;=`<%l$qo)t`VP|W!O`zUOX$qXY)iYZ)iZ]$q]^)i^p$qpq)iqr$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qk+PV{YVP!O`Ov%gwx&Tx!^%g!^!_&o!_;'S%g;'S;=`'W<%lO%g~+iast,n![!]-r!c!}-r#R#S-r#T#o-r%W%o-r%p&a-r&b1p-r4U4d-r4e$IS-r$I`$Ib-r$Kh%#t-r&/x&Et-r&FV;'S-r;'S;:j/c?&r?Ah-r?BY?Mn-r~,qQ!Q![,w#l#m-V~,zQ!Q![,w!]!^-Q~-VOX~~-YR!Q![-c!c!i-c#T#Z-c~-fS!Q![-c!]!^-Q!c!i-c#T#Z-c~-ug}!O-r!O!P-r!Q![-r![!]-r!]!^/^!c!}-r#R#S-r#T#o-r$}%O-r%W%o-r%p&a-r&b1p-r1p4U-r4U4d-r4e$IS-r$I`$Ib-r$Je$Jg-r$Kh%#t-r&/x&Et-r&FV;'S-r;'S;:j/c?&r?Ah-r?BY?Mn-r~/cOW~~/fP;=`<%l-rk/rW}bVP|WOr'^rs&Tsv'^w!^'^!^!_'}!_;'S'^;'S;=`(i<%lO'^k0eZVP|W!O`Or$qrs%gsv$qwx'^x}$q}!O1W!O!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qk1aZVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_!`$q!`!a2S!a;'S$q;'S;=`)c<%lO$qk2_X!PQVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qm3TZVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_!`$q!`!a3v!a;'S$q;'S;=`)c<%lO$qm4RXdSVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qo4{!P`S^QVP|W!O`Or$qrs%gsv$qwx'^x}$q}!O4n!O!P4n!P!Q$q!Q![4n![!]4n!]!^$q!^!_(o!_!c$q!c!}4n!}#R$q#R#S4n#S#T$q#T#o4n#o$}$q$}%O4n%O%W$q%W%o4n%o%p$q%p&a4n&a&b$q&b1p4n1p4U4n4U4d4n4d4e$q4e$IS4n$IS$I`$q$I`$Ib4n$Ib$Je$q$Je$Jg4n$Jg$Kh$q$Kh%#t4n%#t&/x$q&/x&Et4n&Et&FV$q&FV;'S4n;'S;:j8O;:j;=`)c<%l?&r$q?&r?Ah4n?Ah?BY$q?BY?Mn4n?MnO$qo8RP;=`<%l4ni8]Y|W!O`Oq(oqr8{rs&osv(owx'}x!a(o!a!b!#U!b;'S(o;'S;=`)]<%lO(oi9S_|W!O`Or(ors&osv(owx'}x}(o}!O:R!O!f(o!f!g;e!g!}(o!}#ODh#O#W(o#W#XLp#X;'S(o;'S;=`)]<%lO(oi:YX|W!O`Or(ors&osv(owx'}x}(o}!O:u!O;'S(o;'S;=`)]<%lO(oi;OV!QP|W!O`Or(ors&osv(owx'}x;'S(o;'S;=`)]<%lO(oi;lX|W!O`Or(ors&osv(owx'}x!q(o!q!r<X!r;'S(o;'S;=`)]<%lO(oi<`X|W!O`Or(ors&osv(owx'}x!e(o!e!f<{!f;'S(o;'S;=`)]<%lO(oi=SX|W!O`Or(ors&osv(owx'}x!v(o!v!w=o!w;'S(o;'S;=`)]<%lO(oi=vX|W!O`Or(ors&osv(owx'}x!{(o!{!|>c!|;'S(o;'S;=`)]<%lO(oi>jX|W!O`Or(ors&osv(owx'}x!r(o!r!s?V!s;'S(o;'S;=`)]<%lO(oi?^X|W!O`Or(ors&osv(owx'}x!g(o!g!h?y!h;'S(o;'S;=`)]<%lO(oi@QY|W!O`Or?yrs@psv?yvwA[wxBdx!`?y!`!aCr!a;'S?y;'S;=`Db<%lO?ya@uV!O`Ov@pvxA[x!`@p!`!aAy!a;'S@p;'S;=`B^<%lO@pPA_TO!`A[!`!aAn!a;'SA[;'S;=`As<%lOA[PAsOiPPAvP;=`<%lA[aBQSiP!O`Ov&ox;'S&o;'S;=`'Q<%lO&oaBaP;=`<%l@pXBiX|WOrBdrsA[svBdvwA[w!`Bd!`!aCU!a;'SBd;'S;=`Cl<%lOBdXC]TiP|WOr'}sv'}w;'S'};'S;=`(c<%lO'}XCoP;=`<%lBdiC{ViP|W!O`Or(ors&osv(owx'}x;'S(o;'S;=`)]<%lO(oiDeP;=`<%l?yiDoZ|W!O`Or(ors&osv(owx'}x!e(o!e!fEb!f#V(o#V#WIr#W;'S(o;'S;=`)]<%lO(oiEiX|W!O`Or(ors&osv(owx'}x!f(o!f!gFU!g;'S(o;'S;=`)]<%lO(oiF]X|W!O`Or(ors&osv(owx'}x!c(o!c!dFx!d;'S(o;'S;=`)]<%lO(oiGPX|W!O`Or(ors&osv(owx'}x!v(o!v!wGl!w;'S(o;'S;=`)]<%lO(oiGsX|W!O`Or(ors&osv(owx'}x!c(o!c!dH`!d;'S(o;'S;=`)]<%lO(oiHgX|W!O`Or(ors&osv(owx'}x!}(o!}#OIS#O;'S(o;'S;=`)]<%lO(oiI]V|W!O`yPOr(ors&osv(owx'}x;'S(o;'S;=`)]<%lO(oiIyX|W!O`Or(ors&osv(owx'}x#W(o#W#XJf#X;'S(o;'S;=`)]<%lO(oiJmX|W!O`Or(ors&osv(owx'}x#T(o#T#UKY#U;'S(o;'S;=`)]<%lO(oiKaX|W!O`Or(ors&osv(owx'}x#h(o#h#iK|#i;'S(o;'S;=`)]<%lO(oiLTX|W!O`Or(ors&osv(owx'}x#T(o#T#UH`#U;'S(o;'S;=`)]<%lO(oiLwX|W!O`Or(ors&osv(owx'}x#c(o#c#dMd#d;'S(o;'S;=`)]<%lO(oiMkX|W!O`Or(ors&osv(owx'}x#V(o#V#WNW#W;'S(o;'S;=`)]<%lO(oiN_X|W!O`Or(ors&osv(owx'}x#h(o#h#iNz#i;'S(o;'S;=`)]<%lO(oi! RX|W!O`Or(ors&osv(owx'}x#m(o#m#n! n#n;'S(o;'S;=`)]<%lO(oi! uX|W!O`Or(ors&osv(owx'}x#d(o#d#e!!b#e;'S(o;'S;=`)]<%lO(oi!!iX|W!O`Or(ors&osv(owx'}x#X(o#X#Y?y#Y;'S(o;'S;=`)]<%lO(oi!#_V!SP|W!O`Or(ors&osv(owx'}x;'S(o;'S;=`)]<%lO(ok!$PXaQVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qo!$wX[UVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qk!%mZVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_!`$q!`!a!&`!a;'S$q;'S;=`)c<%lO$qk!&kX!RQVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$qk!'aZVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_#P$q#P#Q!(S#Q;'S$q;'S;=`)c<%lO$qk!(]ZVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_!`$q!`!a!)O!a;'S$q;'S;=`)c<%lO$qk!)ZXxQVP|W!O`Or$qrs%gsv$qwx'^x!^$q!^!_(o!_;'S$q;'S;=`)c<%lO$q",
|
|
55365
|
-
tokenizers: [startTag, commentContent, piContent, cdataContent, 0, 1, 2, 3, 4],
|
|
55366
|
-
topRules: { "Document": [0, 6] },
|
|
55367
|
-
tokenPrec: 0
|
|
55368
|
-
});
|
|
55369
|
-
function tagName(doc2, tag) {
|
|
55370
|
-
let name2 = tag && tag.getChild("TagName");
|
|
55371
|
-
return name2 ? doc2.sliceString(name2.from, name2.to) : "";
|
|
55372
|
-
}
|
|
55373
|
-
function elementName$1(doc2, tree) {
|
|
55374
|
-
let tag = tree && tree.firstChild;
|
|
55375
|
-
return !tag || tag.name != "OpenTag" ? "" : tagName(doc2, tag);
|
|
55376
|
-
}
|
|
55377
|
-
function attrName(doc2, tag, pos) {
|
|
55378
|
-
let attr = tag && tag.getChildren("Attribute").find((a) => a.from <= pos && a.to >= pos);
|
|
55379
|
-
let name2 = attr && attr.getChild("AttributeName");
|
|
55380
|
-
return name2 ? doc2.sliceString(name2.from, name2.to) : "";
|
|
55381
|
-
}
|
|
55382
|
-
function findParentElement(tree) {
|
|
55383
|
-
for (let cur2 = tree && tree.parent; cur2; cur2 = cur2.parent)
|
|
55384
|
-
if (cur2.name == "Element")
|
|
55385
|
-
return cur2;
|
|
55386
|
-
return null;
|
|
55387
|
-
}
|
|
55388
|
-
function findLocation(state, pos) {
|
|
55389
|
-
var _a2;
|
|
55390
|
-
let at = syntaxTree(state).resolveInner(pos, -1), inTag = null;
|
|
55391
|
-
for (let cur2 = at; !inTag && cur2.parent; cur2 = cur2.parent)
|
|
55392
|
-
if (cur2.name == "OpenTag" || cur2.name == "CloseTag" || cur2.name == "SelfClosingTag" || cur2.name == "MismatchedCloseTag")
|
|
55393
|
-
inTag = cur2;
|
|
55394
|
-
if (inTag && (inTag.to > pos || inTag.lastChild.type.isError)) {
|
|
55395
|
-
let elt = inTag.parent;
|
|
55396
|
-
if (at.name == "TagName")
|
|
55397
|
-
return inTag.name == "CloseTag" || inTag.name == "MismatchedCloseTag" ? { type: "closeTag", from: at.from, context: elt } : { type: "openTag", from: at.from, context: findParentElement(elt) };
|
|
55398
|
-
if (at.name == "AttributeName")
|
|
55399
|
-
return { type: "attrName", from: at.from, context: inTag };
|
|
55400
|
-
if (at.name == "AttributeValue")
|
|
55401
|
-
return { type: "attrValue", from: at.from, context: inTag };
|
|
55402
|
-
let before = at == inTag || at.name == "Attribute" ? at.childBefore(pos) : at;
|
|
55403
|
-
if ((before === null || before === void 0 ? void 0 : before.name) == "StartTag")
|
|
55404
|
-
return { type: "openTag", from: pos, context: findParentElement(elt) };
|
|
55405
|
-
if ((before === null || before === void 0 ? void 0 : before.name) == "StartCloseTag" && before.to <= pos)
|
|
55406
|
-
return { type: "closeTag", from: pos, context: elt };
|
|
55407
|
-
if ((before === null || before === void 0 ? void 0 : before.name) == "Is")
|
|
55408
|
-
return { type: "attrValue", from: pos, context: inTag };
|
|
55409
|
-
if (before)
|
|
55410
|
-
return { type: "attrName", from: pos, context: inTag };
|
|
55411
|
-
return null;
|
|
55412
|
-
} else if (at.name == "StartCloseTag") {
|
|
55413
|
-
return { type: "closeTag", from: pos, context: at.parent };
|
|
55414
|
-
}
|
|
55415
|
-
while (at.parent && at.to == pos && !((_a2 = at.lastChild) === null || _a2 === void 0 ? void 0 : _a2.type.isError))
|
|
55416
|
-
at = at.parent;
|
|
55417
|
-
if (at.name == "Element" || at.name == "Text" || at.name == "Document")
|
|
55418
|
-
return { type: "tag", from: pos, context: at.name == "Element" ? at : findParentElement(at) };
|
|
55419
|
-
return null;
|
|
55420
|
-
}
|
|
55421
|
-
class Element {
|
|
55422
|
-
constructor(spec, attrs, attrValues) {
|
|
55423
|
-
this.attrs = attrs;
|
|
55424
|
-
this.attrValues = attrValues;
|
|
55425
|
-
this.children = [];
|
|
55426
|
-
this.name = spec.name;
|
|
55427
|
-
this.completion = Object.assign(Object.assign({ type: "type" }, spec.completion || {}), { label: this.name });
|
|
55428
|
-
this.openCompletion = Object.assign(Object.assign({}, this.completion), { label: "<" + this.name });
|
|
55429
|
-
this.closeCompletion = Object.assign(Object.assign({}, this.completion), { label: "</" + this.name + ">", boost: 2 });
|
|
55430
|
-
this.closeNameCompletion = Object.assign(Object.assign({}, this.completion), { label: this.name + ">" });
|
|
55431
|
-
this.text = spec.textContent ? spec.textContent.map((s) => ({ label: s, type: "text" })) : [];
|
|
55432
|
-
}
|
|
55433
|
-
}
|
|
55434
|
-
const Identifier$1 = /^[:\-\.\w\u00b7-\uffff]*$/;
|
|
55435
|
-
function attrCompletion(spec) {
|
|
55436
|
-
return Object.assign(Object.assign({ type: "property" }, spec.completion || {}), { label: spec.name });
|
|
55437
|
-
}
|
|
55438
|
-
function valueCompletion(spec) {
|
|
55439
|
-
return typeof spec == "string" ? { label: `"${spec}"`, type: "constant" } : /^"/.test(spec.label) ? spec : Object.assign(Object.assign({}, spec), { label: `"${spec.label}"` });
|
|
55440
|
-
}
|
|
55441
|
-
function completeFromSchema(eltSpecs, attrSpecs) {
|
|
55442
|
-
let allAttrs = [], globalAttrs = [];
|
|
55443
|
-
let attrValues = /* @__PURE__ */ Object.create(null);
|
|
55444
|
-
for (let s of attrSpecs) {
|
|
55445
|
-
let completion2 = attrCompletion(s);
|
|
55446
|
-
allAttrs.push(completion2);
|
|
55447
|
-
if (s.global)
|
|
55448
|
-
globalAttrs.push(completion2);
|
|
55449
|
-
if (s.values)
|
|
55450
|
-
attrValues[s.name] = s.values.map(valueCompletion);
|
|
55451
|
-
}
|
|
55452
|
-
let allElements = [], topElements = [];
|
|
55453
|
-
let byName = /* @__PURE__ */ Object.create(null);
|
|
55454
|
-
for (let s of eltSpecs) {
|
|
55455
|
-
let attrs = globalAttrs, attrVals = attrValues;
|
|
55456
|
-
if (s.attributes)
|
|
55457
|
-
attrs = attrs.concat(s.attributes.map((s2) => {
|
|
55458
|
-
if (typeof s2 == "string")
|
|
55459
|
-
return allAttrs.find((a) => a.label == s2) || { label: s2, type: "property" };
|
|
55460
|
-
if (s2.values) {
|
|
55461
|
-
if (attrVals == attrValues)
|
|
55462
|
-
attrVals = Object.create(attrVals);
|
|
55463
|
-
attrVals[s2.name] = s2.values.map(valueCompletion);
|
|
55464
|
-
}
|
|
55465
|
-
return attrCompletion(s2);
|
|
55466
|
-
}));
|
|
55467
|
-
let elt = new Element(s, attrs, attrVals);
|
|
55468
|
-
byName[elt.name] = elt;
|
|
55469
|
-
allElements.push(elt);
|
|
55470
|
-
if (s.top)
|
|
55471
|
-
topElements.push(elt);
|
|
55472
|
-
}
|
|
55473
|
-
if (!topElements.length)
|
|
55474
|
-
topElements = allElements;
|
|
55475
|
-
for (let i = 0; i < allElements.length; i++) {
|
|
55476
|
-
let s = eltSpecs[i], elt = allElements[i];
|
|
55477
|
-
if (s.children) {
|
|
55478
|
-
for (let ch of s.children)
|
|
55479
|
-
if (byName[ch])
|
|
55480
|
-
elt.children.push(byName[ch]);
|
|
55481
|
-
} else {
|
|
55482
|
-
elt.children = allElements;
|
|
55483
|
-
}
|
|
55484
|
-
}
|
|
55485
|
-
return (cx) => {
|
|
55486
|
-
var _a2;
|
|
55487
|
-
let { doc: doc2 } = cx.state, loc = findLocation(cx.state, cx.pos);
|
|
55488
|
-
if (!loc || loc.type == "tag" && !cx.explicit)
|
|
55489
|
-
return null;
|
|
55490
|
-
let { type: type2, from, context } = loc;
|
|
55491
|
-
if (type2 == "openTag") {
|
|
55492
|
-
let children = topElements;
|
|
55493
|
-
let parentName = elementName$1(doc2, context);
|
|
55494
|
-
if (parentName) {
|
|
55495
|
-
let parent = byName[parentName];
|
|
55496
|
-
children = (parent === null || parent === void 0 ? void 0 : parent.children) || allElements;
|
|
55497
|
-
}
|
|
55498
|
-
return {
|
|
55499
|
-
from,
|
|
55500
|
-
options: children.map((ch) => ch.completion),
|
|
55501
|
-
validFor: Identifier$1
|
|
55502
|
-
};
|
|
55503
|
-
} else if (type2 == "closeTag") {
|
|
55504
|
-
let parentName = elementName$1(doc2, context);
|
|
55505
|
-
return parentName ? {
|
|
55506
|
-
from,
|
|
55507
|
-
to: cx.pos + (doc2.sliceString(cx.pos, cx.pos + 1) == ">" ? 1 : 0),
|
|
55508
|
-
options: [((_a2 = byName[parentName]) === null || _a2 === void 0 ? void 0 : _a2.closeNameCompletion) || { label: parentName + ">", type: "type" }],
|
|
55509
|
-
validFor: Identifier$1
|
|
55510
|
-
} : null;
|
|
55511
|
-
} else if (type2 == "attrName") {
|
|
55512
|
-
let parent = byName[tagName(doc2, context)];
|
|
55513
|
-
return {
|
|
55514
|
-
from,
|
|
55515
|
-
options: (parent === null || parent === void 0 ? void 0 : parent.attrs) || globalAttrs,
|
|
55516
|
-
validFor: Identifier$1
|
|
55517
|
-
};
|
|
55518
|
-
} else if (type2 == "attrValue") {
|
|
55519
|
-
let attr = attrName(doc2, context, from);
|
|
55520
|
-
if (!attr)
|
|
55521
|
-
return null;
|
|
55522
|
-
let parent = byName[tagName(doc2, context)];
|
|
55523
|
-
let values = ((parent === null || parent === void 0 ? void 0 : parent.attrValues) || attrValues)[attr];
|
|
55524
|
-
if (!values || !values.length)
|
|
55525
|
-
return null;
|
|
55526
|
-
return {
|
|
55527
|
-
from,
|
|
55528
|
-
to: cx.pos + (doc2.sliceString(cx.pos, cx.pos + 1) == '"' ? 1 : 0),
|
|
55529
|
-
options: values,
|
|
55530
|
-
validFor: /^"[^"]*"?$/
|
|
55531
|
-
};
|
|
55532
|
-
} else if (type2 == "tag") {
|
|
55533
|
-
let parentName = elementName$1(doc2, context), parent = byName[parentName];
|
|
55534
|
-
let closing2 = [], last = context && context.lastChild;
|
|
55535
|
-
if (parentName && (!last || last.name != "CloseTag" || tagName(doc2, last) != parentName))
|
|
55536
|
-
closing2.push(parent ? parent.closeCompletion : { label: "</" + parentName + ">", type: "type", boost: 2 });
|
|
55537
|
-
let options = closing2.concat(((parent === null || parent === void 0 ? void 0 : parent.children) || (context ? allElements : topElements)).map((e) => e.openCompletion));
|
|
55538
|
-
if (context && (parent === null || parent === void 0 ? void 0 : parent.text.length)) {
|
|
55539
|
-
let openTag = context.firstChild;
|
|
55540
|
-
if (openTag.to > cx.pos - 20 && !/\S/.test(cx.state.sliceDoc(openTag.to, cx.pos)))
|
|
55541
|
-
options = options.concat(parent.text);
|
|
55542
|
-
}
|
|
55543
|
-
return {
|
|
55544
|
-
from,
|
|
55545
|
-
options,
|
|
55546
|
-
validFor: /^<\/?[:\-\.\w\u00b7-\uffff]*$/
|
|
55547
|
-
};
|
|
55548
|
-
} else {
|
|
55549
|
-
return null;
|
|
55550
|
-
}
|
|
55551
|
-
};
|
|
55552
|
-
}
|
|
55553
|
-
const xmlLanguage = /* @__PURE__ */ LRLanguage.define({
|
|
55554
|
-
name: "xml",
|
|
55555
|
-
parser: /* @__PURE__ */ parser$1.configure({
|
|
55556
|
-
props: [
|
|
55557
|
-
/* @__PURE__ */ indentNodeProp.add({
|
|
55558
|
-
Element(context) {
|
|
55559
|
-
let closed = /^\s*<\//.test(context.textAfter);
|
|
55560
|
-
return context.lineIndent(context.node.from) + (closed ? 0 : context.unit);
|
|
55561
|
-
},
|
|
55562
|
-
"OpenTag CloseTag SelfClosingTag"(context) {
|
|
55563
|
-
return context.column(context.node.from) + context.unit;
|
|
55564
|
-
}
|
|
55565
|
-
}),
|
|
55566
|
-
/* @__PURE__ */ foldNodeProp.add({
|
|
55567
|
-
Element(subtree) {
|
|
55568
|
-
let first = subtree.firstChild, last = subtree.lastChild;
|
|
55569
|
-
if (!first || first.name != "OpenTag")
|
|
55570
|
-
return null;
|
|
55571
|
-
return { from: first.to, to: last.name == "CloseTag" ? last.from : subtree.to };
|
|
55572
|
-
}
|
|
55573
|
-
}),
|
|
55574
|
-
/* @__PURE__ */ bracketMatchingHandle.add({
|
|
55575
|
-
"OpenTag CloseTag": (node) => node.getChild("TagName")
|
|
55576
|
-
})
|
|
55577
|
-
]
|
|
55578
|
-
}),
|
|
55579
|
-
languageData: {
|
|
55580
|
-
commentTokens: { block: { open: "<!--", close: "-->" } },
|
|
55581
|
-
indentOnInput: /^\s*<\/$/
|
|
55582
|
-
}
|
|
55583
|
-
});
|
|
55584
|
-
function xml(conf = {}) {
|
|
55585
|
-
let support = [xmlLanguage.data.of({
|
|
55586
|
-
autocomplete: completeFromSchema(conf.elements || [], conf.attributes || [])
|
|
55587
|
-
})];
|
|
55588
|
-
if (conf.autoCloseTags !== false)
|
|
55589
|
-
support.push(autoCloseTags$1);
|
|
55590
|
-
return new LanguageSupport(xmlLanguage, support);
|
|
55591
|
-
}
|
|
55592
|
-
function elementName$2(doc2, tree, max = doc2.length) {
|
|
55593
|
-
if (!tree)
|
|
55594
|
-
return "";
|
|
55595
|
-
let tag = tree.firstChild;
|
|
55596
|
-
let name2 = tag && tag.getChild("TagName");
|
|
55597
|
-
return name2 ? doc2.sliceString(name2.from, Math.min(name2.to, max)) : "";
|
|
55598
|
-
}
|
|
55599
|
-
const autoCloseTags$1 = /* @__PURE__ */ EditorView.inputHandler.of((view, from, to, text, insertTransaction) => {
|
|
55600
|
-
if (view.composing || view.state.readOnly || from != to || text != ">" && text != "/" || !xmlLanguage.isActiveAt(view.state, from, -1))
|
|
55601
|
-
return false;
|
|
55602
|
-
let base2 = insertTransaction(), { state } = base2;
|
|
55603
|
-
let closeTags = state.changeByRange((range) => {
|
|
55604
|
-
var _a2, _b, _c;
|
|
55605
|
-
let { head } = range;
|
|
55606
|
-
let didType = state.doc.sliceString(head - 1, head) == text;
|
|
55607
|
-
let after = syntaxTree(state).resolveInner(head, -1), name2;
|
|
55608
|
-
if (didType && text == ">" && after.name == "EndTag") {
|
|
55609
|
-
let tag = after.parent;
|
|
55610
|
-
if (((_b = (_a2 = tag.parent) === null || _a2 === void 0 ? void 0 : _a2.lastChild) === null || _b === void 0 ? void 0 : _b.name) != "CloseTag" && (name2 = elementName$2(state.doc, tag.parent, head))) {
|
|
55611
|
-
let to2 = head + (state.doc.sliceString(head, head + 1) === ">" ? 1 : 0);
|
|
55612
|
-
let insert2 = `</${name2}>`;
|
|
55613
|
-
return { range, changes: { from: head, to: to2, insert: insert2 } };
|
|
55614
|
-
}
|
|
55615
|
-
} else if (didType && text == "/" && after.name == "StartCloseTag") {
|
|
55616
|
-
let base3 = after.parent;
|
|
55617
|
-
if (after.from == head - 2 && ((_c = base3.lastChild) === null || _c === void 0 ? void 0 : _c.name) != "CloseTag" && (name2 = elementName$2(state.doc, base3, head))) {
|
|
55618
|
-
let to2 = head + (state.doc.sliceString(head, head + 1) === ">" ? 1 : 0);
|
|
55619
|
-
let insert2 = `${name2}>`;
|
|
55620
|
-
return {
|
|
55621
|
-
range: EditorSelection.cursor(head + insert2.length, -1),
|
|
55622
|
-
changes: { from: head, to: to2, insert: insert2 }
|
|
55623
|
-
};
|
|
55624
|
-
}
|
|
55625
|
-
}
|
|
55626
|
-
return { range };
|
|
55627
|
-
});
|
|
55628
|
-
if (closeTags.changes.empty)
|
|
55629
|
-
return false;
|
|
55630
|
-
view.dispatch([
|
|
55631
|
-
base2,
|
|
55632
|
-
state.update(closeTags, {
|
|
55633
|
-
userEvent: "input.complete",
|
|
55634
|
-
scrollIntoView: true
|
|
55635
|
-
})
|
|
55636
|
-
]);
|
|
55637
|
-
return true;
|
|
55638
|
-
});
|
|
55639
56440
|
const SOAP_11_CONTENT_TYPE = "text/xml; charset=utf-8";
|
|
55640
56441
|
const SOAP_12_CONTENT_TYPE = "application/soap+xml; charset=utf-8";
|
|
55641
56442
|
function contentTypeForSoap(version) {
|
|
@@ -55647,7 +56448,7 @@ function withContentType(headers, value) {
|
|
|
55647
56448
|
if (idx === -1) return [...headers, next];
|
|
55648
56449
|
return headers.map((h, i) => i === idx ? { ...h, value, enabled: true } : h);
|
|
55649
56450
|
}
|
|
55650
|
-
const { electron: electron$
|
|
56451
|
+
const { electron: electron$r } = window;
|
|
55651
56452
|
function ParamTree({ params, depth = 0 }) {
|
|
55652
56453
|
if (params.length === 0) {
|
|
55653
56454
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-600 italic", children: "No parameters declared in WSDL." });
|
|
@@ -55673,7 +56474,7 @@ function SoapEditor({ request, onChange }) {
|
|
|
55673
56474
|
let cancelled = false;
|
|
55674
56475
|
(async () => {
|
|
55675
56476
|
try {
|
|
55676
|
-
const result = await electron$
|
|
56477
|
+
const result = await electron$r.wsdlFetch(url);
|
|
55677
56478
|
if (cancelled) return;
|
|
55678
56479
|
setOperations(result.operations);
|
|
55679
56480
|
setEndpoints(result.endpoints);
|
|
@@ -55710,7 +56511,7 @@ function SoapEditor({ request, onChange }) {
|
|
|
55710
56511
|
setFetching(true);
|
|
55711
56512
|
setFetchError(null);
|
|
55712
56513
|
try {
|
|
55713
|
-
const result = await electron$
|
|
56514
|
+
const result = await electron$r.wsdlFetch(soap.wsdlUrl.trim());
|
|
55714
56515
|
setOperations(result.operations);
|
|
55715
56516
|
setEndpoints(result.endpoints);
|
|
55716
56517
|
setTargetNs(result.targetNamespace);
|
|
@@ -55836,7 +56637,7 @@ function SoapEditor({ request, onChange }) {
|
|
|
55836
56637
|
value: soap.envelope ?? "",
|
|
55837
56638
|
height: "100%",
|
|
55838
56639
|
theme: oneDark,
|
|
55839
|
-
extensions: [xml()],
|
|
56640
|
+
extensions: [xml(), commentKeymap],
|
|
55840
56641
|
onChange: (val) => updateSoap({ envelope: val }),
|
|
55841
56642
|
basicSetup: { lineNumbers: true, foldGutter: true }
|
|
55842
56643
|
}
|
|
@@ -55869,7 +56670,7 @@ function SoapEditor({ request, onChange }) {
|
|
|
55869
56670
|
value: soap.envelope ?? "",
|
|
55870
56671
|
height: "100%",
|
|
55871
56672
|
theme: oneDark,
|
|
55872
|
-
extensions: [xml()],
|
|
56673
|
+
extensions: [xml(), commentKeymap],
|
|
55873
56674
|
onChange: (val) => updateSoap({ envelope: val }),
|
|
55874
56675
|
basicSetup: { lineNumbers: true, foldGutter: true }
|
|
55875
56676
|
}
|
|
@@ -55938,7 +56739,7 @@ function BodyTab({ request, onChange }) {
|
|
|
55938
56739
|
height: "300px",
|
|
55939
56740
|
maxHeight: "50vh",
|
|
55940
56741
|
theme: oneDark,
|
|
55941
|
-
extensions: [
|
|
56742
|
+
extensions: [jsonWithComments(), varExt],
|
|
55942
56743
|
onChange: (val) => onChange({ body: { ...body, json: val } }),
|
|
55943
56744
|
basicSetup: { lineNumbers: true, foldGutter: false, autocompletion: false }
|
|
55944
56745
|
}
|
|
@@ -55970,7 +56771,7 @@ function BodyTab({ request, onChange }) {
|
|
|
55970
56771
|
height: "300px",
|
|
55971
56772
|
maxHeight: "50vh",
|
|
55972
56773
|
theme: oneDark,
|
|
55973
|
-
extensions: [varExt],
|
|
56774
|
+
extensions: /xml/i.test(body.rawContentType ?? "") ? [xmlWithComments(), varExt] : [commentKeymap, varExt],
|
|
55974
56775
|
onChange: (val) => onChange({ body: { ...body, raw: val } }),
|
|
55975
56776
|
basicSetup: { lineNumbers: true, foldGutter: false, autocompletion: false }
|
|
55976
56777
|
}
|
|
@@ -55980,7 +56781,7 @@ function BodyTab({ request, onChange }) {
|
|
|
55980
56781
|
mode === "soap" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SoapEditor, { request, onChange }) })
|
|
55981
56782
|
] });
|
|
55982
56783
|
}
|
|
55983
|
-
const { electron: electron$
|
|
56784
|
+
const { electron: electron$q } = window;
|
|
55984
56785
|
const AUTH_TYPES = ["none", "bearer", "basic", "digest", "ntlm", "apikey", "oauth2"];
|
|
55985
56786
|
function AuthTab({ request, onChange }) {
|
|
55986
56787
|
const auth = request.auth;
|
|
@@ -55994,7 +56795,7 @@ function AuthTab({ request, onChange }) {
|
|
|
55994
56795
|
}
|
|
55995
56796
|
async function saveSecret(ref2) {
|
|
55996
56797
|
if (!secretValue || !ref2) return;
|
|
55997
|
-
await electron$
|
|
56798
|
+
await electron$q.setSecret(ref2, secretValue);
|
|
55998
56799
|
setSaved(true);
|
|
55999
56800
|
setSecretValue("");
|
|
56000
56801
|
setTimeout(() => setSaved(false), 2e3);
|
|
@@ -56006,7 +56807,7 @@ function AuthTab({ request, onChange }) {
|
|
|
56006
56807
|
setOauth2Error("");
|
|
56007
56808
|
try {
|
|
56008
56809
|
const vars = {};
|
|
56009
|
-
const result = await electron$
|
|
56810
|
+
const result = await electron$q.oauth2StartFlow(oauth2Auth, vars);
|
|
56010
56811
|
setAuth({
|
|
56011
56812
|
oauth2CachedToken: result.accessToken,
|
|
56012
56813
|
oauth2TokenExpiry: result.expiresAt
|
|
@@ -56024,7 +56825,7 @@ function AuthTab({ request, onChange }) {
|
|
|
56024
56825
|
setOauth2Status("fetching");
|
|
56025
56826
|
setOauth2Error("");
|
|
56026
56827
|
try {
|
|
56027
|
-
const result = await electron$
|
|
56828
|
+
const result = await electron$q.oauth2RefreshToken(oauth2Auth, {}, oauth2RefreshToken);
|
|
56028
56829
|
setAuth({
|
|
56029
56830
|
oauth2CachedToken: result.accessToken,
|
|
56030
56831
|
oauth2TokenExpiry: result.expiresAt
|
|
@@ -56046,14 +56847,14 @@ function AuthTab({ request, onChange }) {
|
|
|
56046
56847
|
if (auth.type !== "oauth2") return null;
|
|
56047
56848
|
const t2 = auth.oauth2CachedToken;
|
|
56048
56849
|
if (!t2) return null;
|
|
56049
|
-
const
|
|
56850
|
+
const preview2 = t2.length > 16 ? `${t2.slice(0, 6)}…${t2.slice(-6)}` : t2;
|
|
56050
56851
|
const expiry = auth.oauth2TokenExpiry;
|
|
56051
56852
|
let expiryLabel = "";
|
|
56052
56853
|
if (expiry) {
|
|
56053
56854
|
const secsLeft = Math.round((expiry - Date.now()) / 1e3);
|
|
56054
56855
|
expiryLabel = secsLeft > 0 ? ` (expires in ${secsLeft}s)` : " (EXPIRED)";
|
|
56055
56856
|
}
|
|
56056
|
-
return `${
|
|
56857
|
+
return `${preview2}${expiryLabel}`;
|
|
56057
56858
|
})();
|
|
56058
56859
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
56059
56860
|
AuthEditor,
|
|
@@ -63268,6 +64069,17 @@ function SchemaTab({ request, onChange }) {
|
|
|
63268
64069
|
}
|
|
63269
64070
|
}
|
|
63270
64071
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
64072
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg border border-amber-700/40 bg-amber-950/20 px-3 py-2 text-[11px] leading-relaxed text-amber-200/90", children: [
|
|
64073
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-amber-300", children: "Schema — a local scratch check." }),
|
|
64074
|
+
" ",
|
|
64075
|
+
"Validate this request's last response against a JSON Schema, right here. It is ",
|
|
64076
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "not saved to the contract and not published" }),
|
|
64077
|
+
" — a dev-time sanity check only. To define what the provider ",
|
|
64078
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("em", { children: "must" }),
|
|
64079
|
+
" return (which drives contract testing), use the ",
|
|
64080
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Contract" }),
|
|
64081
|
+
" tab."
|
|
64082
|
+
] }),
|
|
63271
64083
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
63272
64084
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-surface-600 uppercase tracking-wider font-medium", children: "JSON Schema (draft-07+)" }),
|
|
63273
64085
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -63291,7 +64103,7 @@ function SchemaTab({ request, onChange }) {
|
|
|
63291
64103
|
)
|
|
63292
64104
|
] })
|
|
63293
64105
|
] }),
|
|
63294
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-600", children: "Standalone
|
|
64106
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-600", children: "Standalone — edits here don't touch the contract. Use “Derive from contract” to start from it." }),
|
|
63295
64107
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-surface-700 rounded overflow-hidden", children: [
|
|
63296
64108
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end px-2 py-0.5 bg-surface-800/50 border-b border-surface-700", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
63297
64109
|
"button",
|
|
@@ -63336,7 +64148,7 @@ function SchemaTab({ request, onChange }) {
|
|
|
63336
64148
|
] }) })
|
|
63337
64149
|
] });
|
|
63338
64150
|
}
|
|
63339
|
-
const { electron: electron$
|
|
64151
|
+
const { electron: electron$p } = window;
|
|
63340
64152
|
const EMPTY = { statusCode: 200, headers: [], bodySchema: "" };
|
|
63341
64153
|
function ContractTab({ request, onChange }) {
|
|
63342
64154
|
const activeTab = useStore((s) => s.tabs.find((t2) => t2.id === s.activeTabId));
|
|
@@ -63350,7 +64162,7 @@ function ContractTab({ request, onChange }) {
|
|
|
63350
64162
|
if (!lastResponse?.body) return;
|
|
63351
64163
|
setInferring(true);
|
|
63352
64164
|
try {
|
|
63353
|
-
const schema = await electron$
|
|
64165
|
+
const schema = await electron$p.inferContractSchema(lastResponse.body);
|
|
63354
64166
|
if (schema) update({ bodySchema: schema });
|
|
63355
64167
|
} finally {
|
|
63356
64168
|
setInferring(false);
|
|
@@ -63367,11 +64179,24 @@ function ContractTab({ request, onChange }) {
|
|
|
63367
64179
|
function removeHeader(i) {
|
|
63368
64180
|
update({ headers: (contract.headers ?? []).filter((_, idx) => idx !== i) });
|
|
63369
64181
|
}
|
|
63370
|
-
const
|
|
64182
|
+
const hasContract2 = contract.statusCode !== void 0 || contract.bodySchema?.trim() || contract.headers?.some((h) => h.key);
|
|
63371
64183
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-4 h-full min-h-0", children: [
|
|
63372
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className:
|
|
63373
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className:
|
|
63374
|
-
|
|
64184
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg border border-blue-700/50 bg-blue-950/30 px-3 py-2 text-[11px] leading-relaxed text-blue-200/90", children: [
|
|
64185
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-blue-300", children: "Contract — the published expectation." }),
|
|
64186
|
+
" ",
|
|
64187
|
+
"What this request ",
|
|
64188
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("em", { children: "needs" }),
|
|
64189
|
+
" from the provider: status, body shape, headers. It becomes the ",
|
|
64190
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "consumer pact" }),
|
|
64191
|
+
" used for contract testing (bi-directional verify & ",
|
|
64192
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: "can-i-deploy" }),
|
|
64193
|
+
"). For a throwaway local response check, use the ",
|
|
64194
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Schema" }),
|
|
64195
|
+
" tab."
|
|
64196
|
+
] }),
|
|
64197
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `flex items-center gap-2 px-3 py-2 rounded-lg text-xs border ${hasContract2 ? "bg-blue-950/40 border-blue-700 text-blue-300" : "bg-surface-800 border-surface-700 text-surface-500"}`, children: [
|
|
64198
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `w-2 h-2 rounded-full ${hasContract2 ? "bg-blue-400" : "bg-surface-600"}` }),
|
|
64199
|
+
hasContract2 ? "Contract defined - will be verified in Contract panel" : "No contract defined yet"
|
|
63375
64200
|
] }),
|
|
63376
64201
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
63377
64202
|
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-[10px] text-surface-500 uppercase tracking-wider font-medium block mb-1.5", children: "Expected Status Code" }),
|
|
@@ -63476,7 +64301,66 @@ function ContractTab({ request, onChange }) {
|
|
|
63476
64301
|
] })
|
|
63477
64302
|
] });
|
|
63478
64303
|
}
|
|
63479
|
-
const {
|
|
64304
|
+
const DEFAULTS = { idleSec: 60, totalSec: 300 };
|
|
64305
|
+
function StreamTab({ request, onChange }) {
|
|
64306
|
+
const stream = request.stream ?? {};
|
|
64307
|
+
function setField(key, seconds) {
|
|
64308
|
+
const next = { ...stream };
|
|
64309
|
+
if (seconds.trim() === "") {
|
|
64310
|
+
delete next[key];
|
|
64311
|
+
} else {
|
|
64312
|
+
const n = Number(seconds);
|
|
64313
|
+
if (Number.isNaN(n) || n < 0) return;
|
|
64314
|
+
next[key] = Math.round(n * 1e3);
|
|
64315
|
+
}
|
|
64316
|
+
onChange({ stream: Object.keys(next).length ? next : void 0 });
|
|
64317
|
+
}
|
|
64318
|
+
const toSec = (ms) => ms === void 0 ? "" : String(ms / 1e3);
|
|
64319
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-4 p-1 text-xs max-w-md", children: [
|
|
64320
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-surface-400 leading-relaxed", children: [
|
|
64321
|
+
"Applies when the response is a stream (",
|
|
64322
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: "text/event-stream" }),
|
|
64323
|
+
", NDJSON, or chunked). A stream stays open until the server ends it, you hit Stop, or one of these limits trips. Leave blank for the default; set 0 to disable."
|
|
64324
|
+
] }),
|
|
64325
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
64326
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-300 font-medium", children: "Idle timeout (seconds)" }),
|
|
64327
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
64328
|
+
"input",
|
|
64329
|
+
{
|
|
64330
|
+
type: "number",
|
|
64331
|
+
min: 0,
|
|
64332
|
+
value: toSec(stream.idleMs),
|
|
64333
|
+
onChange: (e) => setField("idleMs", e.target.value),
|
|
64334
|
+
placeholder: `${DEFAULTS.idleSec} (default)`,
|
|
64335
|
+
className: "w-40 bg-surface-800 border border-surface-700 rounded px-2 py-1 focus:outline-none focus:border-blue-500 placeholder-surface-600"
|
|
64336
|
+
}
|
|
64337
|
+
),
|
|
64338
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] text-surface-500", children: "Close if no frame arrives for this long." })
|
|
64339
|
+
] }),
|
|
64340
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
64341
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-300 font-medium", children: "Max duration (seconds)" }),
|
|
64342
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
64343
|
+
"input",
|
|
64344
|
+
{
|
|
64345
|
+
type: "number",
|
|
64346
|
+
min: 0,
|
|
64347
|
+
value: toSec(stream.maxMs),
|
|
64348
|
+
onChange: (e) => setField("maxMs", e.target.value),
|
|
64349
|
+
placeholder: `${DEFAULTS.totalSec} (default)`,
|
|
64350
|
+
className: "w-40 bg-surface-800 border border-surface-700 rounded px-2 py-1 focus:outline-none focus:border-blue-500 placeholder-surface-600"
|
|
64351
|
+
}
|
|
64352
|
+
),
|
|
64353
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] text-surface-500", children: "Total wall-clock cap for the whole stream." })
|
|
64354
|
+
] }),
|
|
64355
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[11px] text-surface-500", children: [
|
|
64356
|
+
"When a limit trips, the stream ends with status ",
|
|
64357
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-amber-400", children: "timed out" }),
|
|
64358
|
+
" ",
|
|
64359
|
+
"and keeps whatever frames arrived. There is also a hard cap of 5000 events."
|
|
64360
|
+
] })
|
|
64361
|
+
] });
|
|
64362
|
+
}
|
|
64363
|
+
const { electron: electron$o } = window;
|
|
63480
64364
|
function formatTime$1(ts) {
|
|
63481
64365
|
const d = new Date(ts);
|
|
63482
64366
|
const hh = String(d.getHours()).padStart(2, "0");
|
|
@@ -63496,14 +64380,14 @@ function WebSocketPanel({ request }) {
|
|
|
63496
64380
|
const [sendText, setSendText] = reactExports.useState("");
|
|
63497
64381
|
const logEndRef = reactExports.useRef(null);
|
|
63498
64382
|
reactExports.useEffect(() => {
|
|
63499
|
-
electron$
|
|
64383
|
+
electron$o.onWsMessage(({ requestId, message }) => {
|
|
63500
64384
|
addWsMessage(requestId, message);
|
|
63501
64385
|
});
|
|
63502
|
-
electron$
|
|
64386
|
+
electron$o.onWsStatus(({ requestId, status, error: error2 }) => {
|
|
63503
64387
|
setWsStatus(requestId, status, error2);
|
|
63504
64388
|
});
|
|
63505
64389
|
return () => {
|
|
63506
|
-
electron$
|
|
64390
|
+
electron$o.offWsEvents();
|
|
63507
64391
|
};
|
|
63508
64392
|
}, [addWsMessage, setWsStatus]);
|
|
63509
64393
|
reactExports.useEffect(() => {
|
|
@@ -63516,19 +64400,19 @@ function WebSocketPanel({ request }) {
|
|
|
63516
64400
|
if (h.enabled && h.key) headers[h.key] = h.value;
|
|
63517
64401
|
}
|
|
63518
64402
|
try {
|
|
63519
|
-
await electron$
|
|
64403
|
+
await electron$o.wsConnect(request.id, request.url, headers);
|
|
63520
64404
|
} catch (err) {
|
|
63521
64405
|
setWsStatus(request.id, "error", err instanceof Error ? err.message : String(err));
|
|
63522
64406
|
}
|
|
63523
64407
|
}
|
|
63524
64408
|
async function disconnect() {
|
|
63525
|
-
await electron$
|
|
64409
|
+
await electron$o.wsDisconnect(request.id);
|
|
63526
64410
|
}
|
|
63527
64411
|
async function sendMessage() {
|
|
63528
64412
|
const text = sendText.trim();
|
|
63529
64413
|
if (!text || !isConnected) return;
|
|
63530
64414
|
try {
|
|
63531
|
-
await electron$
|
|
64415
|
+
await electron$o.wsSend(request.id, text);
|
|
63532
64416
|
const msg = {
|
|
63533
64417
|
id: crypto.randomUUID(),
|
|
63534
64418
|
direction: "sent",
|
|
@@ -63631,20 +64515,6 @@ function WebSocketPanel({ request }) {
|
|
|
63631
64515
|
] })
|
|
63632
64516
|
] });
|
|
63633
64517
|
}
|
|
63634
|
-
function useToast(durationMs = 3e3) {
|
|
63635
|
-
const [toast, setToast] = reactExports.useState(null);
|
|
63636
|
-
const timer = reactExports.useRef(null);
|
|
63637
|
-
function show(msg, ok) {
|
|
63638
|
-
if (timer.current) clearTimeout(timer.current);
|
|
63639
|
-
setToast({ msg, ok });
|
|
63640
|
-
timer.current = setTimeout(() => setToast(null), durationMs);
|
|
63641
|
-
}
|
|
63642
|
-
return { toast, show };
|
|
63643
|
-
}
|
|
63644
|
-
function Toast({ toast }) {
|
|
63645
|
-
if (!toast) return null;
|
|
63646
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `mx-3 mb-2 px-2 py-1.5 rounded text-[11px] flex-shrink-0 ${toast.ok ? "bg-emerald-900/50 text-emerald-300 border border-emerald-800/50" : "bg-red-900/50 text-red-300 border border-red-800/50"}`, children: toast.msg });
|
|
63647
|
-
}
|
|
63648
64518
|
function statusColor$3(code2) {
|
|
63649
64519
|
const d = String(code2)[0];
|
|
63650
64520
|
return d === "2" ? "text-emerald-400" : d === "3" ? "text-amber-400" : "text-red-400";
|
|
@@ -63900,7 +64770,7 @@ function FuzzResultsPanel({ report, onClear }) {
|
|
|
63900
64770
|
] }) })
|
|
63901
64771
|
] });
|
|
63902
64772
|
}
|
|
63903
|
-
const { electron: electron$
|
|
64773
|
+
const { electron: electron$n } = window;
|
|
63904
64774
|
const WRITE_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
63905
64775
|
function FuzzModal({ request, onClose }) {
|
|
63906
64776
|
const environments = useStore((s) => s.environments);
|
|
@@ -63926,7 +64796,7 @@ function FuzzModal({ request, onClose }) {
|
|
|
63926
64796
|
const env = resolveEnvironmentById(environments, activeEnvironmentId);
|
|
63927
64797
|
const envVars = env ? Object.fromEntries(env.variables.filter((v) => v.enabled).map((v) => [v.key, v.value])) : {};
|
|
63928
64798
|
const collectionVars = activeCollectionId ? collections[activeCollectionId]?.data.collectionVariables ?? {} : {};
|
|
63929
|
-
const result = await electron$
|
|
64799
|
+
const result = await electron$n.fuzzContracts({
|
|
63930
64800
|
requests: [request],
|
|
63931
64801
|
envVars,
|
|
63932
64802
|
collectionVars,
|
|
@@ -64018,7 +64888,7 @@ function FuzzModal({ request, onClose }) {
|
|
|
64018
64888
|
}
|
|
64019
64889
|
);
|
|
64020
64890
|
}
|
|
64021
|
-
const { electron: electron$
|
|
64891
|
+
const { electron: electron$m } = window;
|
|
64022
64892
|
const METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "QUERY"];
|
|
64023
64893
|
const METHOD_COLORS = {
|
|
64024
64894
|
GET: "text-emerald-400",
|
|
@@ -64037,8 +64907,14 @@ function deriveHookStatus(r) {
|
|
|
64037
64907
|
if (tests.length === 0) return "skipped";
|
|
64038
64908
|
return tests.every((t2) => t2.passed) ? "passed" : "failed";
|
|
64039
64909
|
}
|
|
64910
|
+
const TAB_HINTS = {
|
|
64911
|
+
schema: "Schema — a local, throwaway JSON-Schema check of the last response. Not saved to the contract, not published.",
|
|
64912
|
+
contract: "Contract — the published expectation (status, body shape, headers) that drives contract testing: consumer pact, bi-directional verify, can-i-deploy.",
|
|
64913
|
+
stream: "Stream — idle and total timeouts for streamed responses (SSE / NDJSON / chunked)."
|
|
64914
|
+
};
|
|
64040
64915
|
function RequestBuilder({ request }) {
|
|
64041
64916
|
const updateRequest = useStore((s) => s.updateRequest);
|
|
64917
|
+
const updateExampleRequest = useStore((s) => s.updateExampleRequest);
|
|
64042
64918
|
const activeEnvironmentId = useStore((s) => s.activeEnvironmentId);
|
|
64043
64919
|
const activeCollectionId = useStore((s) => s.activeCollectionId);
|
|
64044
64920
|
const environments = useStore((s) => s.environments);
|
|
@@ -64051,6 +64927,8 @@ function RequestBuilder({ request }) {
|
|
|
64051
64927
|
const setTabRequestTab = useStore((s) => s.setTabRequestTab);
|
|
64052
64928
|
const addHistoryEntry = useStore((s) => s.addHistoryEntry);
|
|
64053
64929
|
const applyScriptUpdates = useStore((s) => s.applyScriptUpdates);
|
|
64930
|
+
const startLiveStream = useStore((s) => s.startLiveStream);
|
|
64931
|
+
const finishLiveStream = useStore((s) => s.finishLiveStream);
|
|
64054
64932
|
const workspaceSettings = useStore((s) => s.workspace?.settings);
|
|
64055
64933
|
const collectionTls = useStore((s) => activeCollectionId ? s.collections[activeCollectionId]?.data.tls : void 0);
|
|
64056
64934
|
const activeAppTab = useStore((s) => s.tabs.find((t2) => t2.id === s.activeTabId));
|
|
@@ -64071,7 +64949,21 @@ function RequestBuilder({ request }) {
|
|
|
64071
64949
|
});
|
|
64072
64950
|
}
|
|
64073
64951
|
function update(patch) {
|
|
64074
|
-
|
|
64952
|
+
if (activeAppTab?.exampleId) updateExampleRequest(request.id, activeAppTab.exampleId, patch);
|
|
64953
|
+
else updateRequest(request.id, patch);
|
|
64954
|
+
}
|
|
64955
|
+
function handleUrlPaste(e) {
|
|
64956
|
+
const pasted = e.clipboardData.getData("text");
|
|
64957
|
+
if (!pasted.includes("?")) return;
|
|
64958
|
+
const input = e.currentTarget;
|
|
64959
|
+
const start = input.selectionStart ?? request.url.length;
|
|
64960
|
+
const end = input.selectionEnd ?? request.url.length;
|
|
64961
|
+
const resulting = request.url.slice(0, start) + pasted + request.url.slice(end);
|
|
64962
|
+
const split = extractQueryParams(resulting, request.params ?? []);
|
|
64963
|
+
if (split.changed) {
|
|
64964
|
+
e.preventDefault();
|
|
64965
|
+
update({ url: split.url, params: split.params });
|
|
64966
|
+
}
|
|
64075
64967
|
}
|
|
64076
64968
|
const sendSignal = useStore((s) => s.sendSignal);
|
|
64077
64969
|
const lastSendSignal = reactExports.useRef(sendSignal);
|
|
@@ -64121,7 +65013,7 @@ function RequestBuilder({ request }) {
|
|
|
64121
65013
|
activeEnvironmentId
|
|
64122
65014
|
);
|
|
64123
65015
|
const hookSessionVars = useStore.getState().sessionVars;
|
|
64124
|
-
const r = await electron$
|
|
65016
|
+
const r = await electron$m.sendRequest({
|
|
64125
65017
|
...basePayload,
|
|
64126
65018
|
environment: hookEnv,
|
|
64127
65019
|
request: hook,
|
|
@@ -64165,13 +65057,21 @@ function RequestBuilder({ request }) {
|
|
|
64165
65057
|
activeEnvironmentId
|
|
64166
65058
|
);
|
|
64167
65059
|
const freshSessionVars = useStore.getState().sessionVars;
|
|
64168
|
-
const
|
|
64169
|
-
|
|
64170
|
-
|
|
64171
|
-
|
|
64172
|
-
|
|
64173
|
-
|
|
64174
|
-
|
|
65060
|
+
const streamId = crypto.randomUUID();
|
|
65061
|
+
startLiveStream(activeTabId, streamId);
|
|
65062
|
+
let result;
|
|
65063
|
+
try {
|
|
65064
|
+
result = await electron$m.sendRequest({
|
|
65065
|
+
...basePayload,
|
|
65066
|
+
environment: freshEnv,
|
|
65067
|
+
request: mergedRequest,
|
|
65068
|
+
collectionVars: { ...collectionVars, ...freshSessionVars },
|
|
65069
|
+
globals: liveGlobals,
|
|
65070
|
+
streamId
|
|
65071
|
+
});
|
|
65072
|
+
} finally {
|
|
65073
|
+
finishLiveStream(streamId);
|
|
65074
|
+
}
|
|
64175
65075
|
setTabResponse(activeTabId, result.response, result.scriptResult, result.sentRequest);
|
|
64176
65076
|
applyScriptUpdates(result.scriptResult);
|
|
64177
65077
|
collectionVars = { ...collectionVars, ...result.scriptResult.updatedCollectionVars };
|
|
@@ -64193,7 +65093,7 @@ function RequestBuilder({ request }) {
|
|
|
64193
65093
|
activeEnvironmentId
|
|
64194
65094
|
);
|
|
64195
65095
|
const hookSessionVars = useStore.getState().sessionVars;
|
|
64196
|
-
const r = await electron$
|
|
65096
|
+
const r = await electron$m.sendRequest({
|
|
64197
65097
|
...basePayload,
|
|
64198
65098
|
environment: hookEnv,
|
|
64199
65099
|
request: hook,
|
|
@@ -64243,6 +65143,7 @@ function RequestBuilder({ request }) {
|
|
|
64243
65143
|
const hasPostScript = Boolean(request.postRequestScript?.trim());
|
|
64244
65144
|
const isWs = request.protocol === "websocket";
|
|
64245
65145
|
const isSoap = request.protocol === "soap";
|
|
65146
|
+
const isExample = !!activeAppTab?.exampleId;
|
|
64246
65147
|
const tabs = [
|
|
64247
65148
|
// SOAP collapses Params + Body into a single "SOAP" tab — the WSDL drives both.
|
|
64248
65149
|
...!isSoap ? [{ id: "params", label: "Params", count: request.params.filter((p2) => p2.enabled && p2.key).length }] : [],
|
|
@@ -64250,30 +65151,39 @@ function RequestBuilder({ request }) {
|
|
|
64250
65151
|
...!isWs ? [
|
|
64251
65152
|
{ id: "body", label: isSoap ? "SOAP" : "Body", count: request.body.mode !== "none" ? 1 : 0 },
|
|
64252
65153
|
{ id: "auth", label: "Auth", count: request.auth.type !== "none" ? 1 : 0 },
|
|
64253
|
-
|
|
64254
|
-
|
|
64255
|
-
|
|
65154
|
+
...!isExample ? [
|
|
65155
|
+
{ id: "scripts", label: "Scripts", count: (hasPreScript ? 1 : 0) + (hasPostScript ? 1 : 0) },
|
|
65156
|
+
{ id: "schema", label: "Schema", count: request.schema?.trim() ? 1 : 0 },
|
|
65157
|
+
{ id: "contract", label: "Contract", count: request.contract?.statusCode !== void 0 || request.contract?.bodySchema?.trim() || request.contract?.headers?.some((h) => h.key) ? 1 : 0 },
|
|
65158
|
+
{ id: "stream", label: "Stream", count: request.stream?.idleMs !== void 0 || request.stream?.maxMs !== void 0 ? 1 : 0 }
|
|
65159
|
+
] : []
|
|
64256
65160
|
] : []
|
|
64257
65161
|
];
|
|
64258
65162
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col h-full", children: [
|
|
64259
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-3 pb-1 flex-shrink-0", children:
|
|
64260
|
-
|
|
64261
|
-
|
|
64262
|
-
|
|
64263
|
-
|
|
64264
|
-
|
|
64265
|
-
|
|
64266
|
-
|
|
64267
|
-
|
|
64268
|
-
|
|
64269
|
-
|
|
64270
|
-
|
|
64271
|
-
|
|
64272
|
-
|
|
64273
|
-
|
|
64274
|
-
|
|
64275
|
-
|
|
64276
|
-
|
|
65163
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 pt-3 pb-1 flex-shrink-0 flex items-center justify-between gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex items-center gap-2", children: [
|
|
65164
|
+
editingName ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
65165
|
+
"input",
|
|
65166
|
+
{
|
|
65167
|
+
autoFocus: true,
|
|
65168
|
+
value: request.name,
|
|
65169
|
+
onChange: (e) => update({ name: e.target.value }),
|
|
65170
|
+
onBlur: () => setEditingName(false),
|
|
65171
|
+
onKeyDown: (e) => e.key === "Enter" && setEditingName(false),
|
|
65172
|
+
className: "text-sm font-medium bg-transparent border-b border-blue-500 focus:outline-none w-full"
|
|
65173
|
+
}
|
|
65174
|
+
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
65175
|
+
"button",
|
|
65176
|
+
{
|
|
65177
|
+
onClick: () => setEditingName(true),
|
|
65178
|
+
className: "text-sm font-medium text-white hover:text-blue-400 transition-colors text-left truncate",
|
|
65179
|
+
children: request.name
|
|
65180
|
+
}
|
|
65181
|
+
),
|
|
65182
|
+
activeAppTab?.exampleId && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "shrink-0 text-[10px] uppercase tracking-wider text-amber-400 border border-amber-500/30 rounded px-1.5 py-0.5", children: [
|
|
65183
|
+
"Example: ",
|
|
65184
|
+
request.examples?.find((e) => e.id === activeAppTab.exampleId)?.name ?? ""
|
|
65185
|
+
] })
|
|
65186
|
+
] }) }),
|
|
64277
65187
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 px-4 py-2 flex-shrink-0", children: [
|
|
64278
65188
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex bg-surface-800 border border-surface-700 rounded overflow-hidden text-xs font-bold flex-shrink-0", children: [
|
|
64279
65189
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -64357,6 +65267,7 @@ function RequestBuilder({ request }) {
|
|
|
64357
65267
|
{
|
|
64358
65268
|
value: request.url,
|
|
64359
65269
|
onChange: (url) => update({ url }),
|
|
65270
|
+
onPaste: handleUrlPaste,
|
|
64360
65271
|
placeholder: isWs ? "ws://example.com/socket" : isSoap ? "Endpoint (auto-filled from WSDL <soap:address>)" : "https://api.example.com/endpoint",
|
|
64361
65272
|
wrapperClassName: "flex-1",
|
|
64362
65273
|
className: `border rounded px-3 py-1.5 text-sm focus:outline-none focus:border-blue-500 font-mono placeholder-surface-700 ${isSoap ? "bg-surface-900 border-amber-900/50 text-surface-300" : "bg-surface-800 border-surface-700"}`
|
|
@@ -64390,6 +65301,7 @@ function RequestBuilder({ request }) {
|
|
|
64390
65301
|
"button",
|
|
64391
65302
|
{
|
|
64392
65303
|
onClick: () => setActiveTab(tab.id),
|
|
65304
|
+
title: TAB_HINTS[tab.id],
|
|
64393
65305
|
className: `px-3 py-1.5 text-xs transition-colors border-b-2 -mb-px ${activeTab === tab.id ? "border-blue-500 text-white" : "border-transparent text-surface-400 hover:text-white"}`,
|
|
64394
65306
|
children: [
|
|
64395
65307
|
tab.label,
|
|
@@ -64409,15 +65321,19 @@ function RequestBuilder({ request }) {
|
|
|
64409
65321
|
}
|
|
64410
65322
|
)
|
|
64411
65323
|
] }),
|
|
64412
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
64413
|
-
activeTab === "
|
|
64414
|
-
|
|
64415
|
-
|
|
64416
|
-
|
|
64417
|
-
|
|
64418
|
-
|
|
64419
|
-
|
|
64420
|
-
|
|
65324
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-3 flex-1 overflow-y-auto min-h-0", children: /* @__PURE__ */ (() => {
|
|
65325
|
+
const shown = isExample && (activeTab === "scripts" || activeTab === "schema" || activeTab === "contract" || activeTab === "stream") ? "body" : activeTab;
|
|
65326
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
65327
|
+
shown === "params" && /* @__PURE__ */ jsxRuntimeExports.jsx(ParamsTab, { request, onChange: update }),
|
|
65328
|
+
shown === "headers" && /* @__PURE__ */ jsxRuntimeExports.jsx(HeadersTab, { request, onChange: update }),
|
|
65329
|
+
shown === "body" && /* @__PURE__ */ jsxRuntimeExports.jsx(BodyTab, { request, onChange: update }),
|
|
65330
|
+
shown === "auth" && /* @__PURE__ */ jsxRuntimeExports.jsx(AuthTab, { request, onChange: update }),
|
|
65331
|
+
!isExample && shown === "scripts" && /* @__PURE__ */ jsxRuntimeExports.jsx(ScriptsTab, { request, onChange: update }),
|
|
65332
|
+
!isExample && shown === "schema" && /* @__PURE__ */ jsxRuntimeExports.jsx(SchemaTab, { request, onChange: update }),
|
|
65333
|
+
!isExample && shown === "contract" && /* @__PURE__ */ jsxRuntimeExports.jsx(ContractTab, { request, onChange: update }),
|
|
65334
|
+
!isExample && shown === "stream" && /* @__PURE__ */ jsxRuntimeExports.jsx(StreamTab, { request, onChange: update })
|
|
65335
|
+
] });
|
|
65336
|
+
})() })
|
|
64421
65337
|
] })
|
|
64422
65338
|
] });
|
|
64423
65339
|
}
|
|
@@ -64667,13 +65583,13 @@ function AssertMenu({ state, onClose, onConfirm }) {
|
|
|
64667
65583
|
if (state.type === "json") {
|
|
64668
65584
|
const { path, value, root: root2 } = state;
|
|
64669
65585
|
const isStr = typeof value === "string";
|
|
64670
|
-
const
|
|
65586
|
+
const preview2 = isStr ? `"${value.length > 22 ? value.slice(0, 22) + "…" : value}"` : String(value);
|
|
64671
65587
|
title2 = jsonPathLabel(path);
|
|
64672
65588
|
options = [
|
|
64673
|
-
{ label: `equals ${
|
|
65589
|
+
{ label: `equals ${preview2}`, snippet: makeJsonSnippet(path, value, "equals") },
|
|
64674
65590
|
{ label: "exists (not null/undefined)", snippet: makeJsonSnippet(path, value, "exists") },
|
|
64675
65591
|
{ label: `is ${value === null ? "null" : typeof value}`, snippet: makeJsonSnippet(path, value, "type") },
|
|
64676
|
-
...isStr ? [{ label: `contains ${
|
|
65592
|
+
...isStr ? [{ label: `contains ${preview2}`, snippet: makeJsonSnippet(path, value, "contains") }] : []
|
|
64677
65593
|
];
|
|
64678
65594
|
const arrayIdx = [...path].reverse().findIndex((k) => typeof k === "number");
|
|
64679
65595
|
if (arrayIdx >= 0) {
|
|
@@ -64697,12 +65613,12 @@ function AssertMenu({ state, onClose, onConfirm }) {
|
|
|
64697
65613
|
}
|
|
64698
65614
|
} else {
|
|
64699
65615
|
const { selector, value } = state;
|
|
64700
|
-
const
|
|
65616
|
+
const preview2 = `"${value.length > 22 ? value.slice(0, 22) + "…" : value}"`;
|
|
64701
65617
|
title2 = selector;
|
|
64702
65618
|
options = [
|
|
64703
|
-
{ label: `equals ${
|
|
65619
|
+
{ label: `equals ${preview2}`, snippet: makeXmlSnippet(selector, value, "equals") },
|
|
64704
65620
|
{ label: "exists", snippet: makeXmlSnippet(selector, value, "exists") },
|
|
64705
|
-
{ label: `contains ${
|
|
65621
|
+
{ label: `contains ${preview2}`, snippet: makeXmlSnippet(selector, value, "contains") }
|
|
64706
65622
|
];
|
|
64707
65623
|
}
|
|
64708
65624
|
const x = Math.min(state.x, window.innerWidth - 280);
|
|
@@ -64912,6 +65828,128 @@ function InteractiveBody({ body, contentType, onAssert }) {
|
|
|
64912
65828
|
treeContent
|
|
64913
65829
|
] });
|
|
64914
65830
|
}
|
|
65831
|
+
const { electron: electron$l } = window;
|
|
65832
|
+
const RENDER_TAIL = 500;
|
|
65833
|
+
const CLOSE_LABEL = {
|
|
65834
|
+
complete: "closed",
|
|
65835
|
+
stopped: "stopped",
|
|
65836
|
+
error: "error",
|
|
65837
|
+
timeout: "timed out"
|
|
65838
|
+
};
|
|
65839
|
+
const CLOSE_COLOR = {
|
|
65840
|
+
complete: "text-emerald-400",
|
|
65841
|
+
stopped: "text-surface-400",
|
|
65842
|
+
error: "text-red-400",
|
|
65843
|
+
timeout: "text-amber-400"
|
|
65844
|
+
};
|
|
65845
|
+
function eventName(ev) {
|
|
65846
|
+
if (ev.kind === "sse") return ev.name ?? "message";
|
|
65847
|
+
if (ev.kind === "ndjson") return "json";
|
|
65848
|
+
return null;
|
|
65849
|
+
}
|
|
65850
|
+
function preview(ev) {
|
|
65851
|
+
if (ev.json !== void 0) {
|
|
65852
|
+
try {
|
|
65853
|
+
return JSON.stringify(ev.json);
|
|
65854
|
+
} catch {
|
|
65855
|
+
}
|
|
65856
|
+
}
|
|
65857
|
+
return ev.data;
|
|
65858
|
+
}
|
|
65859
|
+
function StreamView({ events, streaming, streamId, streamClose, firstEventMs }) {
|
|
65860
|
+
const [mode, setMode] = reactExports.useState("events");
|
|
65861
|
+
const [stopping, setStopping] = reactExports.useState(false);
|
|
65862
|
+
const bottomRef = reactExports.useRef(null);
|
|
65863
|
+
reactExports.useEffect(() => {
|
|
65864
|
+
if (streaming && mode === "events") bottomRef.current?.scrollIntoView({ block: "nearest" });
|
|
65865
|
+
}, [events.length, streaming, mode]);
|
|
65866
|
+
const shown = events.length > RENDER_TAIL ? events.slice(-RENDER_TAIL) : events;
|
|
65867
|
+
const firstMs = firstEventMs ?? events[0]?.tMs;
|
|
65868
|
+
async function stop() {
|
|
65869
|
+
if (!streamId) return;
|
|
65870
|
+
setStopping(true);
|
|
65871
|
+
try {
|
|
65872
|
+
await electron$l.stopStream(streamId);
|
|
65873
|
+
} catch {
|
|
65874
|
+
}
|
|
65875
|
+
}
|
|
65876
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "h-full flex flex-col min-h-0", children: [
|
|
65877
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 px-3 py-1.5 border-b border-surface-800 text-[11px] shrink-0", children: [
|
|
65878
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex items-center gap-1.5", children: streaming ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
65879
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-2 h-2 rounded-full bg-emerald-400 animate-pulse" }),
|
|
65880
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-emerald-400 font-medium", children: "streaming" })
|
|
65881
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
65882
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `w-2 h-2 rounded-full ${streamClose === "error" ? "bg-red-400" : streamClose === "timeout" ? "bg-amber-400" : "bg-surface-500"}` }),
|
|
65883
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: streamClose ? CLOSE_COLOR[streamClose] : "text-surface-400", children: streamClose ? CLOSE_LABEL[streamClose] : "closed" })
|
|
65884
|
+
] }) }),
|
|
65885
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-400 font-mono", children: [
|
|
65886
|
+
events.length,
|
|
65887
|
+
" ",
|
|
65888
|
+
events.length === 1 ? "event" : "events"
|
|
65889
|
+
] }),
|
|
65890
|
+
firstMs !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-500 font-mono", title: "Time to first event", children: [
|
|
65891
|
+
"first +",
|
|
65892
|
+
firstMs,
|
|
65893
|
+
"ms"
|
|
65894
|
+
] }),
|
|
65895
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ml-auto flex items-center gap-2", children: [
|
|
65896
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex rounded border border-surface-700 overflow-hidden", children: [
|
|
65897
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
65898
|
+
"button",
|
|
65899
|
+
{
|
|
65900
|
+
onClick: () => setMode("events"),
|
|
65901
|
+
className: `px-2 py-0.5 text-[10px] transition-colors ${mode === "events" ? "bg-surface-700 text-white" : "text-surface-500 hover:text-white"}`,
|
|
65902
|
+
children: "Events"
|
|
65903
|
+
}
|
|
65904
|
+
),
|
|
65905
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
65906
|
+
"button",
|
|
65907
|
+
{
|
|
65908
|
+
onClick: () => setMode("merged"),
|
|
65909
|
+
className: `px-2 py-0.5 text-[10px] transition-colors ${mode === "merged" ? "bg-surface-700 text-white" : "text-surface-500 hover:text-white"}`,
|
|
65910
|
+
children: "Merged"
|
|
65911
|
+
}
|
|
65912
|
+
)
|
|
65913
|
+
] }),
|
|
65914
|
+
streaming && streamId && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
65915
|
+
"button",
|
|
65916
|
+
{
|
|
65917
|
+
onClick: stop,
|
|
65918
|
+
disabled: stopping,
|
|
65919
|
+
className: "px-2 py-0.5 text-[10px] rounded bg-red-900/40 text-red-300 hover:bg-red-900/60 disabled:opacity-50 transition-colors",
|
|
65920
|
+
children: stopping ? "Stopping…" : "Stop"
|
|
65921
|
+
}
|
|
65922
|
+
)
|
|
65923
|
+
] })
|
|
65924
|
+
] }),
|
|
65925
|
+
events.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex items-center justify-center text-surface-500 text-xs", children: streaming ? "Waiting for the first event…" : "No events received." }) : mode === "merged" ? /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "flex-1 overflow-auto m-0 px-3 py-2 text-[11px] font-mono text-surface-300 whitespace-pre-wrap break-words", children: shown.map((e) => e.data).join("\n") }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-auto min-h-0", children: [
|
|
65926
|
+
events.length > RENDER_TAIL && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "px-3 py-1 text-[10px] text-surface-500 bg-surface-900/50 sticky top-0", children: [
|
|
65927
|
+
"showing the last ",
|
|
65928
|
+
RENDER_TAIL,
|
|
65929
|
+
" of ",
|
|
65930
|
+
events.length,
|
|
65931
|
+
" events"
|
|
65932
|
+
] }),
|
|
65933
|
+
shown.map((ev) => {
|
|
65934
|
+
const name2 = eventName(ev);
|
|
65935
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-baseline gap-2 px-3 py-1 border-b border-surface-800/60 hover:bg-surface-800/40", children: [
|
|
65936
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] font-mono text-surface-600 w-10 shrink-0 text-right tabular-nums", children: [
|
|
65937
|
+
"#",
|
|
65938
|
+
ev.seq
|
|
65939
|
+
] }),
|
|
65940
|
+
name2 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] font-mono px-1 py-px rounded bg-surface-700/60 text-surface-300 shrink-0", children: name2 }),
|
|
65941
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[9px] font-mono text-surface-600 shrink-0 tabular-nums", title: "Time since request start", children: [
|
|
65942
|
+
"+",
|
|
65943
|
+
ev.tMs,
|
|
65944
|
+
"ms"
|
|
65945
|
+
] }),
|
|
65946
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono text-surface-200 truncate", title: ev.data, children: preview(ev) })
|
|
65947
|
+
] }, ev.seq);
|
|
65948
|
+
}),
|
|
65949
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: bottomRef })
|
|
65950
|
+
] })
|
|
65951
|
+
] });
|
|
65952
|
+
}
|
|
64915
65953
|
const HOOK_BADGE$1 = {
|
|
64916
65954
|
beforeAll: { label: "BEFORE ALL", cls: "bg-violet-700 text-white" },
|
|
64917
65955
|
before: { label: "BEFORE", cls: "bg-violet-600 text-white" },
|
|
@@ -64993,7 +66031,7 @@ function HookResultsPanel({ results }) {
|
|
|
64993
66031
|
}) })
|
|
64994
66032
|
] });
|
|
64995
66033
|
}
|
|
64996
|
-
const { electron: electron$
|
|
66034
|
+
const { electron: electron$k } = window;
|
|
64997
66035
|
function extractPath(url) {
|
|
64998
66036
|
try {
|
|
64999
66037
|
return new URL(url).pathname || "/";
|
|
@@ -65047,14 +66085,14 @@ function SaveAsMockModal({ onClose }) {
|
|
|
65047
66085
|
const entry = state.mocks[serverId];
|
|
65048
66086
|
const updated = { ...entry.data, name: newServerName, port: Number(newServerPort), routes: [route] };
|
|
65049
66087
|
updateMock(serverId, updated);
|
|
65050
|
-
await electron$
|
|
66088
|
+
await electron$k.saveMock(entry.relPath, updated);
|
|
65051
66089
|
const ws2 = useStore.getState().workspace;
|
|
65052
|
-
if (ws2) await electron$
|
|
66090
|
+
if (ws2) await electron$k.saveWorkspace(ws2);
|
|
65053
66091
|
} else {
|
|
65054
66092
|
const entry = useStore.getState().mocks[serverId];
|
|
65055
66093
|
const updated = { ...entry.data, routes: [...entry.data.routes, route] };
|
|
65056
66094
|
updateMock(serverId, updated);
|
|
65057
|
-
await electron$
|
|
66095
|
+
await electron$k.saveMock(entry.relPath, updated);
|
|
65058
66096
|
}
|
|
65059
66097
|
onClose();
|
|
65060
66098
|
} finally {
|
|
@@ -65481,7 +66519,7 @@ function validateHttpSemantics(res, opts = {}) {
|
|
|
65481
66519
|
const order = { error: 0, warning: 1, hint: 2 };
|
|
65482
66520
|
return f.sort((a, b) => order[a.severity] - order[b.severity]);
|
|
65483
66521
|
}
|
|
65484
|
-
const { electron: electron$
|
|
66522
|
+
const { electron: electron$j } = window;
|
|
65485
66523
|
function xmlWellFormed(body) {
|
|
65486
66524
|
try {
|
|
65487
66525
|
const doc2 = new DOMParser().parseFromString(body, "application/xml");
|
|
@@ -65573,6 +66611,8 @@ function ResponseViewer() {
|
|
|
65573
66611
|
const setTabRequestTab = useStore((s) => s.setTabRequestTab);
|
|
65574
66612
|
const setTabScriptTab = useStore((s) => s.setTabScriptTab);
|
|
65575
66613
|
const isSending = activeTab?.isSending ?? false;
|
|
66614
|
+
const liveStream = useStore((s) => s.liveStream);
|
|
66615
|
+
const streamForTab = liveStream && liveStream.tabId === activeTabId ? liveStream : null;
|
|
65576
66616
|
const response = activeTab?.lastResponse ?? null;
|
|
65577
66617
|
const scriptResult = activeTab?.lastScriptResult ?? null;
|
|
65578
66618
|
const sentRequest = activeTab?.lastSentRequest ?? null;
|
|
@@ -65617,7 +66657,7 @@ function ResponseViewer() {
|
|
|
65617
66657
|
const contractToast = useToast(2500);
|
|
65618
66658
|
async function saveAsContract() {
|
|
65619
66659
|
if (!response || !requestId || !activeTabId) return;
|
|
65620
|
-
const schema = response.body ? await electron$
|
|
66660
|
+
const schema = response.body ? await electron$j.inferContractSchema(response.body) : null;
|
|
65621
66661
|
const contentType2 = response.headers["content-type"];
|
|
65622
66662
|
const headers = contentType2 ? [{ key: "content-type", value: contentType2, required: true }] : [];
|
|
65623
66663
|
updateRequest(requestId, {
|
|
@@ -65645,6 +66685,16 @@ function ResponseViewer() {
|
|
|
65645
66685
|
assertToast.show("✓ Assertion added", true);
|
|
65646
66686
|
}
|
|
65647
66687
|
if (isSending) {
|
|
66688
|
+
if (streamForTab && (streamForTab.streaming || streamForTab.events.length > 0)) {
|
|
66689
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
66690
|
+
StreamView,
|
|
66691
|
+
{
|
|
66692
|
+
events: streamForTab.events,
|
|
66693
|
+
streaming: streamForTab.streaming,
|
|
66694
|
+
streamId: streamForTab.streamId
|
|
66695
|
+
}
|
|
66696
|
+
);
|
|
66697
|
+
}
|
|
65648
66698
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-full flex items-center justify-center text-surface-400 text-sm", children: "Sending..." });
|
|
65649
66699
|
}
|
|
65650
66700
|
if (!response) {
|
|
@@ -65723,7 +66773,7 @@ function ResponseViewer() {
|
|
|
65723
66773
|
!response.error && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ml-auto flex items-center gap-1 shrink-0", children: [
|
|
65724
66774
|
assertToast.toast && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-emerald-400 font-medium px-1", children: assertToast.toast.msg }),
|
|
65725
66775
|
contractToast.toast && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-blue-400 font-medium px-1", children: contractToast.toast.msg }),
|
|
65726
|
-
tab === "body" && supportsTree && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex rounded overflow-hidden border border-surface-800 mr-1", children: [
|
|
66776
|
+
tab === "body" && supportsTree && !response.streamed && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex rounded overflow-hidden border border-surface-800 mr-1", children: [
|
|
65727
66777
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
65728
66778
|
"button",
|
|
65729
66779
|
{
|
|
@@ -65785,7 +66835,15 @@ function ResponseViewer() {
|
|
|
65785
66835
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0 flex flex-col overflow-y-auto", children: response.error ? tab === "request" ? /* @__PURE__ */ jsxRuntimeExports.jsx(RequestPanel, { sentRequest }) : tab === "history" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0 overflow-y-auto", children: historyContent }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col p-4 gap-2", children: [
|
|
65786
66836
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-red-400 text-sm font-medium", children: "Request failed" }),
|
|
65787
66837
|
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-xs text-red-300 whitespace-pre-wrap", children: response.error })
|
|
65788
|
-
] }) : diffMode && pinnedResponse ? /* @__PURE__ */ jsxRuntimeExports.jsx(DiffView, { pinned: pinnedResponse, current: response }) : tab === "body" &&
|
|
66838
|
+
] }) : diffMode && pinnedResponse ? /* @__PURE__ */ jsxRuntimeExports.jsx(DiffView, { pinned: pinnedResponse, current: response }) : tab === "body" && response.streamed ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
66839
|
+
StreamView,
|
|
66840
|
+
{
|
|
66841
|
+
events: response.events ?? [],
|
|
66842
|
+
streaming: false,
|
|
66843
|
+
streamClose: response.streamClose,
|
|
66844
|
+
firstEventMs: response.firstEventMs
|
|
66845
|
+
}
|
|
66846
|
+
) : tab === "body" && supportsTree && bodyView === "tree" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
65789
66847
|
InteractiveBody,
|
|
65790
66848
|
{
|
|
65791
66849
|
body: response.body,
|
|
@@ -65907,7 +66965,7 @@ function ResponseViewer() {
|
|
|
65907
66965
|
] }) })
|
|
65908
66966
|
] });
|
|
65909
66967
|
}
|
|
65910
|
-
const { electron: electron$
|
|
66968
|
+
const { electron: electron$i } = window;
|
|
65911
66969
|
const TARGETS = [
|
|
65912
66970
|
{ id: "robot_framework", label: "Robot Framework", description: "Python RequestsLibrary keywords + test suite" },
|
|
65913
66971
|
{ id: "playwright_ts", label: "Playwright TS", description: "TypeScript page-object API classes + spec files" },
|
|
@@ -65948,7 +67006,7 @@ function GeneratorPanel() {
|
|
|
65948
67006
|
try {
|
|
65949
67007
|
const col = collections[selectedCollectionId]?.data;
|
|
65950
67008
|
const env = resolveEnvironmentById(environments, activeEnvironmentId);
|
|
65951
|
-
const generated = await electron$
|
|
67009
|
+
const generated = await electron$i.generateCode({ collection: col, environment: env, target });
|
|
65952
67010
|
setFiles(generated);
|
|
65953
67011
|
setSelectedFile(generated[0]?.path ?? null);
|
|
65954
67012
|
} catch (e) {
|
|
@@ -65960,7 +67018,7 @@ function GeneratorPanel() {
|
|
|
65960
67018
|
async function saveZip() {
|
|
65961
67019
|
if (files.length === 0) return;
|
|
65962
67020
|
const col = collections[selectedCollectionId]?.data;
|
|
65963
|
-
await electron$
|
|
67021
|
+
await electron$i.saveGeneratedFilesAsZip(files, col?.name ?? "api-tests", target);
|
|
65964
67022
|
}
|
|
65965
67023
|
const selectedContent = files.find((f) => f.path === selectedFile)?.content ?? "";
|
|
65966
67024
|
const activeTarget = TARGETS.find((t2) => t2.id === target);
|
|
@@ -66144,7 +67202,7 @@ function historyToHar(entries, creatorVersion = "1.0") {
|
|
|
66144
67202
|
}
|
|
66145
67203
|
}, null, 2);
|
|
66146
67204
|
}
|
|
66147
|
-
const { electron: electron$
|
|
67205
|
+
const { electron: electron$h } = window;
|
|
66148
67206
|
const STATUS_COLOR = {
|
|
66149
67207
|
"2": "text-emerald-400",
|
|
66150
67208
|
"3": "text-amber-400",
|
|
@@ -66192,7 +67250,7 @@ function HistoryPanel() {
|
|
|
66192
67250
|
}
|
|
66193
67251
|
async function downloadHar() {
|
|
66194
67252
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace(/[:T]/g, "-");
|
|
66195
|
-
await electron$
|
|
67253
|
+
await electron$h.saveResults(historyToHar(history2), `api-spector-history-${stamp}.har`);
|
|
66196
67254
|
}
|
|
66197
67255
|
function open(entry) {
|
|
66198
67256
|
setSelected(entry);
|
|
@@ -66323,30 +67381,30 @@ function HistoryRow({
|
|
|
66323
67381
|
}
|
|
66324
67382
|
);
|
|
66325
67383
|
}
|
|
66326
|
-
const { electron: electron$
|
|
67384
|
+
const { electron: electron$g } = window;
|
|
66327
67385
|
function WelcomeScreen() {
|
|
66328
67386
|
const { applyWorkspace } = useWorkspaceLoader();
|
|
66329
67387
|
const [recents, setRecents] = reactExports.useState([]);
|
|
66330
67388
|
const [update, setUpdate] = reactExports.useState(null);
|
|
66331
67389
|
reactExports.useEffect(() => {
|
|
66332
|
-
electron$
|
|
66333
|
-
electron$
|
|
67390
|
+
electron$g.getRecentWorkspaces().then(setRecents).catch(() => setRecents([]));
|
|
67391
|
+
electron$g.checkForUpdate().then((info) => {
|
|
66334
67392
|
if (info?.updateAvailable) setUpdate(info);
|
|
66335
67393
|
}).catch(() => {
|
|
66336
67394
|
});
|
|
66337
67395
|
}, []);
|
|
66338
67396
|
async function openWorkspace() {
|
|
66339
|
-
const result = await electron$
|
|
67397
|
+
const result = await electron$g.openWorkspace();
|
|
66340
67398
|
if (!result) return;
|
|
66341
67399
|
await applyWorkspace(result.workspace, result.workspacePath);
|
|
66342
67400
|
}
|
|
66343
67401
|
async function newWorkspace() {
|
|
66344
|
-
const result = await electron$
|
|
67402
|
+
const result = await electron$g.newWorkspace();
|
|
66345
67403
|
if (!result) return;
|
|
66346
67404
|
await applyWorkspace(result.workspace, result.workspacePath);
|
|
66347
67405
|
}
|
|
66348
67406
|
async function openRecent(path) {
|
|
66349
|
-
const result = await electron$
|
|
67407
|
+
const result = await electron$g.openWorkspacePath(path);
|
|
66350
67408
|
if (!result) {
|
|
66351
67409
|
setRecents((prev) => prev.filter((r) => r.path !== path));
|
|
66352
67410
|
return;
|
|
@@ -66386,7 +67444,7 @@ function WelcomeScreen() {
|
|
|
66386
67444
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-surface-400 text-sm max-w-sm", children: "Local-first API testing with Robot Framework & Playwright code generation. Secrets stay on your machine." }),
|
|
66387
67445
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[11px] mt-3", style: { color: "var(--text-muted)" }, children: [
|
|
66388
67446
|
"version ",
|
|
66389
|
-
"0.4.
|
|
67447
|
+
"0.4.7"
|
|
66390
67448
|
] })
|
|
66391
67449
|
] }),
|
|
66392
67450
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3 w-64", children: [
|
|
@@ -66430,7 +67488,7 @@ function WelcomeScreen() {
|
|
|
66430
67488
|
] })
|
|
66431
67489
|
] });
|
|
66432
67490
|
}
|
|
66433
|
-
const { electron: electron$
|
|
67491
|
+
const { electron: electron$f } = window;
|
|
66434
67492
|
const EXAMPLES = [
|
|
66435
67493
|
{
|
|
66436
67494
|
label: "macOS / Linux (~/.zshrc or ~/.bashrc)",
|
|
@@ -66454,7 +67512,7 @@ function MasterKeyModal({ onSuccess, onCancel }) {
|
|
|
66454
67512
|
setError("Password cannot be empty.");
|
|
66455
67513
|
return;
|
|
66456
67514
|
}
|
|
66457
|
-
await electron$
|
|
67515
|
+
await electron$f.setMasterKey(password);
|
|
66458
67516
|
onSuccess(password);
|
|
66459
67517
|
}
|
|
66460
67518
|
function copy(idx, text) {
|
|
@@ -66538,7 +67596,7 @@ function MasterKeyModal({ onSuccess, onCancel }) {
|
|
|
66538
67596
|
}
|
|
66539
67597
|
);
|
|
66540
67598
|
}
|
|
66541
|
-
const { electron: electron$
|
|
67599
|
+
const { electron: electron$e } = window;
|
|
66542
67600
|
async function shortHash(value) {
|
|
66543
67601
|
const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
|
|
66544
67602
|
return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 8);
|
|
@@ -66665,7 +67723,7 @@ function EnvironmentEditor({ onClose }) {
|
|
|
66665
67723
|
async function saveEncrypted(idx) {
|
|
66666
67724
|
const plaintext = secretInputs[idx] ?? "";
|
|
66667
67725
|
if (!plaintext) return;
|
|
66668
|
-
const { set: set2 } = await electron$
|
|
67726
|
+
const { set: set2 } = await electron$e.checkMasterKey();
|
|
66669
67727
|
if (!set2) {
|
|
66670
67728
|
setPendingEncryptIdx(idx);
|
|
66671
67729
|
return;
|
|
@@ -66702,9 +67760,9 @@ function EnvironmentEditor({ onClose }) {
|
|
|
66702
67760
|
} : state.workspace
|
|
66703
67761
|
}));
|
|
66704
67762
|
const ws2 = useStore.getState().workspace;
|
|
66705
|
-
if (ws2) await electron$
|
|
67763
|
+
if (ws2) await electron$e.saveWorkspace(ws2);
|
|
66706
67764
|
}
|
|
66707
|
-
await electron$
|
|
67765
|
+
await electron$e.saveEnvironment(newRelPath, env);
|
|
66708
67766
|
}
|
|
66709
67767
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
66710
67768
|
pendingEncryptIdx !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -67014,7 +68072,7 @@ function EnvironmentEditor({ onClose }) {
|
|
|
67014
68072
|
)
|
|
67015
68073
|
] });
|
|
67016
68074
|
}
|
|
67017
|
-
const { electron: electron$
|
|
68075
|
+
const { electron: electron$d } = window;
|
|
67018
68076
|
function EnvironmentBar({ inline = false }) {
|
|
67019
68077
|
const environments = useStore((s) => s.environments);
|
|
67020
68078
|
const activeEnvironmentId = useStore((s) => s.activeEnvironmentId);
|
|
@@ -67029,7 +68087,7 @@ function EnvironmentBar({ inline = false }) {
|
|
|
67029
68087
|
if (id2) {
|
|
67030
68088
|
const hasSecrets = environments[id2]?.data.variables.some((v) => v.enabled && v.secret);
|
|
67031
68089
|
if (hasSecrets) {
|
|
67032
|
-
const { set: set2 } = await electron$
|
|
68090
|
+
const { set: set2 } = await electron$d.checkMasterKey();
|
|
67033
68091
|
if (!set2) {
|
|
67034
68092
|
setPendingEnvId(id2);
|
|
67035
68093
|
return;
|
|
@@ -67083,7 +68141,7 @@ function EnvironmentBar({ inline = false }) {
|
|
|
67083
68141
|
controls
|
|
67084
68142
|
] });
|
|
67085
68143
|
}
|
|
67086
|
-
const { electron: electron$
|
|
68144
|
+
const { electron: electron$c } = window;
|
|
67087
68145
|
const DEFAULT_PII_PATTERNS = ["authorization", "password", "token", "secret", "api-key", "x-api-key"];
|
|
67088
68146
|
const ZOOM_STEPS = [0.75, 0.9, 1, 1.1, 1.25, 1.5];
|
|
67089
68147
|
function WorkspaceSettingsModal({ onClose }) {
|
|
@@ -67109,6 +68167,20 @@ function WorkspaceSettingsModal({ onClose }) {
|
|
|
67109
68167
|
// default true
|
|
67110
68168
|
);
|
|
67111
68169
|
const [dashboardUrl, setDashboardUrl] = reactExports.useState(existing.dashboardUrl ?? "");
|
|
68170
|
+
const [cloudEnabled2, setCloudEnabled] = reactExports.useState(existing.cloud?.enabled ?? false);
|
|
68171
|
+
const [cloudToken, setCloudToken] = reactExports.useState("");
|
|
68172
|
+
const cloudTokenSet = existing.cloud?.tokenSet ?? false;
|
|
68173
|
+
const [cloudTest, setCloudTest] = reactExports.useState({ status: "idle" });
|
|
68174
|
+
async function testCloud() {
|
|
68175
|
+
setCloudTest({ status: "testing" });
|
|
68176
|
+
try {
|
|
68177
|
+
if (cloudToken.trim()) await electron$c.setSecret("cloud:token", cloudToken.trim());
|
|
68178
|
+
const me = await electron$c.cloudTest();
|
|
68179
|
+
setCloudTest({ status: "ok", msg: `Connected as ${me.email} · ${me.organization} (${me.plan})` });
|
|
68180
|
+
} catch (e) {
|
|
68181
|
+
setCloudTest({ status: "err", msg: e.message });
|
|
68182
|
+
}
|
|
68183
|
+
}
|
|
67112
68184
|
const [patterns, setPatterns] = reactExports.useState(
|
|
67113
68185
|
existing.piiMaskPatterns ?? DEFAULT_PII_PATTERNS
|
|
67114
68186
|
);
|
|
@@ -67142,15 +68214,24 @@ function WorkspaceSettingsModal({ onClose }) {
|
|
|
67142
68214
|
settings.piiMaskPatterns = patterns;
|
|
67143
68215
|
if (dashboardUrl.trim()) settings.dashboardUrl = dashboardUrl.trim();
|
|
67144
68216
|
else delete settings.dashboardUrl;
|
|
68217
|
+
if (cloudEnabled2 || cloudTokenSet || cloudToken.trim()) {
|
|
68218
|
+
settings.cloud = {
|
|
68219
|
+
enabled: cloudEnabled2,
|
|
68220
|
+
tokenSet: cloudTokenSet || Boolean(cloudToken.trim())
|
|
68221
|
+
};
|
|
68222
|
+
} else {
|
|
68223
|
+
delete settings.cloud;
|
|
68224
|
+
}
|
|
68225
|
+
if (cloudToken.trim()) await electron$c.setSecret("cloud:token", cloudToken.trim());
|
|
67145
68226
|
if (defaultEnvironment) settings.defaultEnvironment = defaultEnvironment;
|
|
67146
68227
|
else delete settings.defaultEnvironment;
|
|
67147
68228
|
if (persistHistory) settings.persistHistory = true;
|
|
67148
68229
|
else delete settings.persistHistory;
|
|
67149
68230
|
updateWorkspaceSettings(settings);
|
|
67150
68231
|
const updated = useStore.getState().workspace;
|
|
67151
|
-
if (updated) await electron$
|
|
68232
|
+
if (updated) await electron$c.saveWorkspace(updated);
|
|
67152
68233
|
if (persistHistory) {
|
|
67153
|
-
await electron$
|
|
68234
|
+
await electron$c.saveHistory(useStore.getState().history).catch(() => {
|
|
67154
68235
|
});
|
|
67155
68236
|
}
|
|
67156
68237
|
onClose();
|
|
@@ -67166,7 +68247,8 @@ function WorkspaceSettingsModal({ onClose }) {
|
|
|
67166
68247
|
{ id: "proxy", label: "Proxy" },
|
|
67167
68248
|
{ id: "tls", label: "TLS / Certificates" },
|
|
67168
68249
|
{ id: "privacy", label: "Privacy" },
|
|
67169
|
-
{ id: "contracts", label: "Contracts" }
|
|
68250
|
+
{ id: "contracts", label: "Contracts" },
|
|
68251
|
+
{ id: "cloud", label: "Cloud" }
|
|
67170
68252
|
];
|
|
67171
68253
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
67172
68254
|
Modal,
|
|
@@ -67323,6 +68405,56 @@ function WorkspaceSettingsModal({ onClose }) {
|
|
|
67323
68405
|
] }),
|
|
67324
68406
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-surface-600 text-[11px]", children: 'Where your contract dashboard is served (api-spector contract report --serve, locally or as a docker container). Adds an "Open dashboard" link to the contract results panel. The link is view-only: recorded results reach the dashboard through the workspace files, not through this URL.' })
|
|
67325
68407
|
] }),
|
|
68408
|
+
activeTab === "cloud" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
68409
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-start gap-2 cursor-pointer", children: [
|
|
68410
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
68411
|
+
"input",
|
|
68412
|
+
{
|
|
68413
|
+
type: "checkbox",
|
|
68414
|
+
checked: cloudEnabled2,
|
|
68415
|
+
onChange: (e) => setCloudEnabled(e.target.checked),
|
|
68416
|
+
className: "mt-0.5 accent-blue-500"
|
|
68417
|
+
}
|
|
68418
|
+
),
|
|
68419
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex flex-col gap-0.5", children: [
|
|
68420
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-200", children: "Enable API Spector Cloud" }),
|
|
68421
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-[11px]", children: 'Push mocks and monitors to a hosted instance. When on, "Push to cloud" actions appear on mocks and requests.' })
|
|
68422
|
+
] })
|
|
68423
|
+
] }),
|
|
68424
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
68425
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-[10px] uppercase tracking-wider text-surface-600 font-medium", children: "API token" }),
|
|
68426
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
68427
|
+
"input",
|
|
68428
|
+
{
|
|
68429
|
+
type: "password",
|
|
68430
|
+
value: cloudToken,
|
|
68431
|
+
onChange: (e) => setCloudToken(e.target.value),
|
|
68432
|
+
placeholder: cloudTokenSet ? "•••••••• (saved — type to replace)" : "Paste a token from the cloud dashboard",
|
|
68433
|
+
className: "bg-surface-800 border border-surface-700 rounded px-2.5 py-1.5 focus:outline-none focus:border-blue-500 font-mono placeholder-surface-600"
|
|
68434
|
+
}
|
|
68435
|
+
),
|
|
68436
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-[11px]", children: "Stored in your OS keychain, never in the workspace file. Create one under Tokens in the cloud dashboard." })
|
|
68437
|
+
] }),
|
|
68438
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
68439
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
68440
|
+
"button",
|
|
68441
|
+
{
|
|
68442
|
+
onClick: testCloud,
|
|
68443
|
+
disabled: cloudTest.status === "testing",
|
|
68444
|
+
className: "px-3 py-1.5 bg-surface-700 hover:bg-surface-600 disabled:opacity-40 rounded transition-colors",
|
|
68445
|
+
children: cloudTest.status === "testing" ? "Testing…" : "Test connection"
|
|
68446
|
+
}
|
|
68447
|
+
),
|
|
68448
|
+
cloudTest.status === "ok" && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-green-400 text-[11px]", children: [
|
|
68449
|
+
"✓ ",
|
|
68450
|
+
cloudTest.msg
|
|
68451
|
+
] }),
|
|
68452
|
+
cloudTest.status === "err" && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-red-400 text-[11px]", children: [
|
|
68453
|
+
"✗ ",
|
|
68454
|
+
cloudTest.msg
|
|
68455
|
+
] })
|
|
68456
|
+
] })
|
|
68457
|
+
] }),
|
|
67326
68458
|
activeTab === "tls" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
67327
68459
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
67328
68460
|
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-[10px] uppercase tracking-wider text-surface-600 font-medium", children: "CA Certificate path" }),
|
|
@@ -67441,7 +68573,7 @@ function WorkspaceSettingsModal({ onClose }) {
|
|
|
67441
68573
|
}
|
|
67442
68574
|
);
|
|
67443
68575
|
}
|
|
67444
|
-
const { electron: electron$
|
|
68576
|
+
const { electron: electron$b } = window;
|
|
67445
68577
|
function DocsGeneratorModal({ onClose }) {
|
|
67446
68578
|
const collections = useStore((s) => s.collections);
|
|
67447
68579
|
const collectionList = Object.values(collections);
|
|
@@ -67450,7 +68582,7 @@ function DocsGeneratorModal({ onClose }) {
|
|
|
67450
68582
|
);
|
|
67451
68583
|
const [format2, setFormat] = reactExports.useState("markdown");
|
|
67452
68584
|
const [generating, setGenerating] = reactExports.useState(false);
|
|
67453
|
-
const [
|
|
68585
|
+
const [preview2, setPreview] = reactExports.useState(null);
|
|
67454
68586
|
const [error2, setError] = reactExports.useState(null);
|
|
67455
68587
|
function toggleCollection(id2) {
|
|
67456
68588
|
setSelectedIds((prev) => {
|
|
@@ -67481,9 +68613,9 @@ function DocsGeneratorModal({ onClose }) {
|
|
|
67481
68613
|
setGenerating(true);
|
|
67482
68614
|
setError(null);
|
|
67483
68615
|
try {
|
|
67484
|
-
const content2 = await electron$
|
|
68616
|
+
const content2 = await electron$b.generateDocs(buildPayload());
|
|
67485
68617
|
const filename = format2 === "html" ? "api-docs.html" : "api-docs.md";
|
|
67486
|
-
await electron$
|
|
68618
|
+
await electron$b.saveResults(content2, filename);
|
|
67487
68619
|
} catch (err) {
|
|
67488
68620
|
setError(err instanceof Error ? err.message : String(err));
|
|
67489
68621
|
} finally {
|
|
@@ -67494,7 +68626,7 @@ function DocsGeneratorModal({ onClose }) {
|
|
|
67494
68626
|
setGenerating(true);
|
|
67495
68627
|
setError(null);
|
|
67496
68628
|
try {
|
|
67497
|
-
const content2 = await electron$
|
|
68629
|
+
const content2 = await electron$b.generateDocs(buildPayload());
|
|
67498
68630
|
setPreview(content2);
|
|
67499
68631
|
} catch (err) {
|
|
67500
68632
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -67562,7 +68694,7 @@ function DocsGeneratorModal({ onClose }) {
|
|
|
67562
68694
|
] }, f)) })
|
|
67563
68695
|
] }),
|
|
67564
68696
|
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-red-400", children: error2 }),
|
|
67565
|
-
|
|
68697
|
+
preview2 !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
67566
68698
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-1", children: [
|
|
67567
68699
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] font-semibold uppercase tracking-wider text-surface-600", children: "Preview" }),
|
|
67568
68700
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -67577,7 +68709,7 @@ function DocsGeneratorModal({ onClose }) {
|
|
|
67577
68709
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded overflow-hidden border border-surface-700", style: { height: 280 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
67578
68710
|
ReactCodeMirror,
|
|
67579
68711
|
{
|
|
67580
|
-
value:
|
|
68712
|
+
value: preview2,
|
|
67581
68713
|
height: "280px",
|
|
67582
68714
|
theme: oneDark,
|
|
67583
68715
|
extensions: [],
|
|
@@ -67843,7 +68975,7 @@ function parseCurl(command2) {
|
|
|
67843
68975
|
}
|
|
67844
68976
|
return { name: name2, method: resolvedMethod, url, headers, params: [], auth, body };
|
|
67845
68977
|
}
|
|
67846
|
-
const { electron: electron$
|
|
68978
|
+
const { electron: electron$a } = window;
|
|
67847
68979
|
const OPTIONS = [
|
|
67848
68980
|
{ id: "postman", label: "Postman", description: "Collection v2.1 JSON" },
|
|
67849
68981
|
{ id: "openapi", label: "OpenAPI", description: "JSON or YAML (v3.x)", supportsUrl: true },
|
|
@@ -67918,12 +69050,12 @@ function ImportModal({ onImport, onClose }) {
|
|
|
67918
69050
|
setError(null);
|
|
67919
69051
|
try {
|
|
67920
69052
|
let col = null;
|
|
67921
|
-
if (opt2.id === "postman") col = await electron$
|
|
67922
|
-
if (opt2.id === "openapi") col = await electron$
|
|
67923
|
-
if (opt2.id === "insomnia") col = await electron$
|
|
67924
|
-
if (opt2.id === "bruno") col = await electron$
|
|
67925
|
-
if (opt2.id === "http") col = await electron$
|
|
67926
|
-
if (opt2.id === "spector") col = await electron$
|
|
69053
|
+
if (opt2.id === "postman") col = await electron$a.importPostman();
|
|
69054
|
+
if (opt2.id === "openapi") col = await electron$a.importOpenApi();
|
|
69055
|
+
if (opt2.id === "insomnia") col = await electron$a.importInsomnia();
|
|
69056
|
+
if (opt2.id === "bruno") col = await electron$a.importBruno();
|
|
69057
|
+
if (opt2.id === "http") col = await electron$a.importHttpFile();
|
|
69058
|
+
if (opt2.id === "spector") col = await electron$a.importSpectorCollection();
|
|
67927
69059
|
if (!col) {
|
|
67928
69060
|
setLoading(false);
|
|
67929
69061
|
return;
|
|
@@ -67946,7 +69078,7 @@ function ImportModal({ onImport, onClose }) {
|
|
|
67946
69078
|
setLoading(true);
|
|
67947
69079
|
setError(null);
|
|
67948
69080
|
try {
|
|
67949
|
-
const col = await electron$
|
|
69081
|
+
const col = await electron$a.importOpenApiFromUrl(trimmed);
|
|
67950
69082
|
if (col) enterPreview(col);
|
|
67951
69083
|
} catch (err) {
|
|
67952
69084
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -68053,7 +69185,7 @@ function ImportModal({ onImport, onClose }) {
|
|
|
68053
69185
|
mergeIntoCollection(target, prunedRoot, prunedRequests);
|
|
68054
69186
|
const entry = useStore.getState().collections[target];
|
|
68055
69187
|
if (entry) {
|
|
68056
|
-
await electron$
|
|
69188
|
+
await electron$a.saveCollection(entry.relPath, entry.data);
|
|
68057
69189
|
markCollectionClean(target);
|
|
68058
69190
|
}
|
|
68059
69191
|
setActiveCollection(target);
|
|
@@ -68080,7 +69212,7 @@ function ImportModal({ onImport, onClose }) {
|
|
|
68080
69212
|
variables: [{ key: name2, value, enabled: true }]
|
|
68081
69213
|
};
|
|
68082
69214
|
const relPath = envRelPath(finalName, envId);
|
|
68083
|
-
await electron$
|
|
69215
|
+
await electron$a.saveEnvironment(relPath, env);
|
|
68084
69216
|
useStore.setState((s) => {
|
|
68085
69217
|
s.environments[envId] = { relPath, data: env };
|
|
68086
69218
|
if (!s.activeEnvironmentId) s.activeEnvironmentId = envId;
|
|
@@ -68090,7 +69222,7 @@ function ImportModal({ onImport, onClose }) {
|
|
|
68090
69222
|
return s;
|
|
68091
69223
|
});
|
|
68092
69224
|
const ws2 = useStore.getState().workspace;
|
|
68093
|
-
if (ws2) await electron$
|
|
69225
|
+
if (ws2) await electron$a.saveWorkspace(ws2);
|
|
68094
69226
|
} else {
|
|
68095
69227
|
const entry = state.environments[envTarget];
|
|
68096
69228
|
if (!entry) throw new Error("Target environment not found");
|
|
@@ -68105,7 +69237,7 @@ function ImportModal({ onImport, onClose }) {
|
|
|
68105
69237
|
} else {
|
|
68106
69238
|
updated.variables = [...updated.variables, { key: name2, value, enabled: true }];
|
|
68107
69239
|
}
|
|
68108
|
-
await electron$
|
|
69240
|
+
await electron$a.saveEnvironment(entry.relPath, updated);
|
|
68109
69241
|
useStore.getState().updateEnvironment(envTarget, updated);
|
|
68110
69242
|
}
|
|
68111
69243
|
}
|
|
@@ -68481,7 +69613,7 @@ function collectRequestsByFolder(folder, src) {
|
|
|
68481
69613
|
walk(folder);
|
|
68482
69614
|
return out;
|
|
68483
69615
|
}
|
|
68484
|
-
const { electron: electron$
|
|
69616
|
+
const { electron: electron$9 } = window;
|
|
68485
69617
|
function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
68486
69618
|
const { applyWorkspace } = useWorkspaceLoader();
|
|
68487
69619
|
const workspace = useStore((s) => s.workspace);
|
|
@@ -68504,13 +69636,13 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
68504
69636
|
try {
|
|
68505
69637
|
for (const { relPath, data, dirty } of Object.values(collections)) {
|
|
68506
69638
|
if (!dirty) continue;
|
|
68507
|
-
await electron$
|
|
69639
|
+
await electron$9.saveCollection(relPath, data);
|
|
68508
69640
|
markCollectionClean(data.id);
|
|
68509
69641
|
}
|
|
68510
69642
|
for (const { relPath, data } of Object.values(environments)) {
|
|
68511
|
-
await electron$
|
|
69643
|
+
await electron$9.saveEnvironment(relPath, data);
|
|
68512
69644
|
}
|
|
68513
|
-
if (workspace) await electron$
|
|
69645
|
+
if (workspace) await electron$9.saveWorkspace(workspace);
|
|
68514
69646
|
} finally {
|
|
68515
69647
|
setSaving(false);
|
|
68516
69648
|
}
|
|
@@ -68518,14 +69650,14 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
68518
69650
|
async function afterImport(col) {
|
|
68519
69651
|
if (!col) return;
|
|
68520
69652
|
const relPath = colRelPath(col.name, col.id);
|
|
68521
|
-
await electron$
|
|
69653
|
+
await electron$9.saveCollection(relPath, col);
|
|
68522
69654
|
loadCollection(relPath, col);
|
|
68523
69655
|
setActiveCollection(col.id);
|
|
68524
69656
|
const ws2 = useStore.getState().workspace;
|
|
68525
69657
|
if (ws2 && !ws2.collections.includes(relPath)) {
|
|
68526
69658
|
const updated = { ...ws2, collections: [...ws2.collections, relPath] };
|
|
68527
69659
|
useStore.setState({ workspace: updated });
|
|
68528
|
-
await electron$
|
|
69660
|
+
await electron$9.saveWorkspace(updated);
|
|
68529
69661
|
}
|
|
68530
69662
|
}
|
|
68531
69663
|
if (!workspace) return null;
|
|
@@ -68614,7 +69746,7 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
68614
69746
|
"button",
|
|
68615
69747
|
{
|
|
68616
69748
|
onClick: async () => {
|
|
68617
|
-
const result = await electron$
|
|
69749
|
+
const result = await electron$9.openWorkspace();
|
|
68618
69750
|
if (result) await applyWorkspace(result.workspace, result.workspacePath);
|
|
68619
69751
|
},
|
|
68620
69752
|
className: "px-2.5 py-1 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
@@ -68626,7 +69758,7 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
68626
69758
|
"button",
|
|
68627
69759
|
{
|
|
68628
69760
|
onClick: async () => {
|
|
68629
|
-
const result = await electron$
|
|
69761
|
+
const result = await electron$9.newWorkspace();
|
|
68630
69762
|
if (result) await applyWorkspace(result.workspace, result.workspacePath);
|
|
68631
69763
|
},
|
|
68632
69764
|
className: "px-2.5 py-1 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
@@ -68638,7 +69770,7 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
68638
69770
|
"button",
|
|
68639
69771
|
{
|
|
68640
69772
|
onClick: async () => {
|
|
68641
|
-
await electron$
|
|
69773
|
+
await electron$9.closeWorkspace();
|
|
68642
69774
|
closeWorkspace();
|
|
68643
69775
|
},
|
|
68644
69776
|
className: "px-2.5 py-1 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
@@ -69089,7 +70221,7 @@ api-tests:
|
|
|
69089
70221
|
function EmptyState({ message }) {
|
|
69090
70222
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-24 text-surface-400 text-xs", children: message });
|
|
69091
70223
|
}
|
|
69092
|
-
const { electron: electron$
|
|
70224
|
+
const { electron: electron$8 } = window;
|
|
69093
70225
|
const HOOK_BADGE = {
|
|
69094
70226
|
beforeAll: { label: "BEFORE ALL", cls: "bg-violet-700 text-white" },
|
|
69095
70227
|
before: { label: "BEFORE", cls: "bg-violet-600 text-white" },
|
|
@@ -69209,13 +70341,13 @@ function RunnerModal() {
|
|
|
69209
70341
|
setSummary(null);
|
|
69210
70342
|
setRunnerRunning(true);
|
|
69211
70343
|
progressIdxRef.current = 0;
|
|
69212
|
-
electron$
|
|
70344
|
+
electron$8.onRunProgress((result) => {
|
|
69213
70345
|
const idx = progressIdxRef.current;
|
|
69214
70346
|
patchRunnerResult(idx, result);
|
|
69215
70347
|
if (result.status !== "running") progressIdxRef.current++;
|
|
69216
70348
|
});
|
|
69217
70349
|
try {
|
|
69218
|
-
const s = await electron$
|
|
70350
|
+
const s = await electron$8.runCollection({
|
|
69219
70351
|
items: items2,
|
|
69220
70352
|
environment: env,
|
|
69221
70353
|
globals,
|
|
@@ -69226,7 +70358,7 @@ function RunnerModal() {
|
|
|
69226
70358
|
});
|
|
69227
70359
|
setSummary(s);
|
|
69228
70360
|
} finally {
|
|
69229
|
-
electron$
|
|
70361
|
+
electron$8.offRunProgress();
|
|
69230
70362
|
setRunnerRunning(false);
|
|
69231
70363
|
}
|
|
69232
70364
|
}, [collectionId, folderId, filterTags, selectedEnvId, environments, globals, colEntry, requestDelay, workspaceSettings, setRunnerResults, patchRunnerResult, setRunnerRunning]);
|
|
@@ -69452,7 +70584,7 @@ function RunnerModal() {
|
|
|
69452
70584
|
};
|
|
69453
70585
|
const content2 = exportFormat === "junit" ? buildJUnitReport(runnerResults, summary, meta2) : exportFormat === "html" ? buildHtmlReport(runnerResults, summary, meta2) : buildJsonReport(runnerResults, summary, meta2);
|
|
69454
70586
|
const ext = exportFormat === "junit" ? "xml" : exportFormat === "html" ? "html" : "json";
|
|
69455
|
-
electron$
|
|
70587
|
+
electron$8.saveResults(content2, `spector-results.${ext}`);
|
|
69456
70588
|
},
|
|
69457
70589
|
className: "px-2.5 py-0.5 bg-surface-800 hover:bg-surface-700 rounded transition-colors text-[11px] whitespace-nowrap",
|
|
69458
70590
|
children: "Export results"
|
|
@@ -69536,8 +70668,117 @@ function CollectionPanel() {
|
|
|
69536
70668
|
] })
|
|
69537
70669
|
] });
|
|
69538
70670
|
}
|
|
69539
|
-
|
|
70671
|
+
function routeKey(method, path) {
|
|
70672
|
+
return `${(method || "GET").toUpperCase()} /${String(path || "").replace(/^\/+/, "")}`;
|
|
70673
|
+
}
|
|
70674
|
+
function PushToCloudModal({ mock, onClose }) {
|
|
70675
|
+
const routes = mock.routes ?? [];
|
|
70676
|
+
const [selected, setSelected] = reactExports.useState(new Set(routes.map((r) => r.id)));
|
|
70677
|
+
const [status, setStatus] = reactExports.useState({ state: "idle" });
|
|
70678
|
+
const [existing, setExisting] = reactExports.useState(null);
|
|
70679
|
+
reactExports.useEffect(() => {
|
|
70680
|
+
let live = true;
|
|
70681
|
+
getCloudMockRoutes(mock.name).then((cloudRoutes) => {
|
|
70682
|
+
if (!live) return;
|
|
70683
|
+
setExisting(cloudRoutes ? new Set(cloudRoutes.map((r) => routeKey(r.method, r.path))) : /* @__PURE__ */ new Set());
|
|
70684
|
+
});
|
|
70685
|
+
return () => {
|
|
70686
|
+
live = false;
|
|
70687
|
+
};
|
|
70688
|
+
}, [mock.name]);
|
|
70689
|
+
const isExisting = (r) => existing?.has(routeKey(r.method, r.path)) ?? false;
|
|
70690
|
+
const selectedRoutes = routes.filter((r) => selected.has(r.id));
|
|
70691
|
+
const overwriteCount = selectedRoutes.filter(isExisting).length;
|
|
70692
|
+
const addCount = selectedRoutes.length - overwriteCount;
|
|
70693
|
+
const allSelected = routes.length > 0 && selected.size === routes.length;
|
|
70694
|
+
function toggle(id2) {
|
|
70695
|
+
setSelected((prev) => {
|
|
70696
|
+
const next = new Set(prev);
|
|
70697
|
+
if (next.has(id2)) next.delete(id2);
|
|
70698
|
+
else next.add(id2);
|
|
70699
|
+
return next;
|
|
70700
|
+
});
|
|
70701
|
+
}
|
|
70702
|
+
async function push2() {
|
|
70703
|
+
setStatus({ state: "pushing" });
|
|
70704
|
+
try {
|
|
70705
|
+
const r = await pushMockToCloud(mock, [...selected]);
|
|
70706
|
+
setStatus({ state: "ok", msg: r.url });
|
|
70707
|
+
} catch (e) {
|
|
70708
|
+
setStatus({ state: "err", msg: e.message });
|
|
70709
|
+
}
|
|
70710
|
+
}
|
|
70711
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
70712
|
+
Modal,
|
|
70713
|
+
{
|
|
70714
|
+
onClose,
|
|
70715
|
+
overlayClassName: "bg-black/50 z-50 flex items-start justify-center pt-24",
|
|
70716
|
+
panelClassName: "bg-surface-900 border border-surface-800 rounded-lg shadow-2xl w-[480px] flex flex-col max-h-[70vh]",
|
|
70717
|
+
title: `Push "${mock.name}" to cloud`,
|
|
70718
|
+
children: [
|
|
70719
|
+
overwriteCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-4 mt-3 px-3 py-2 rounded bg-amber-900/30 border border-amber-800/50 text-amber-300 text-[11px] flex-shrink-0", children: [
|
|
70720
|
+
"⚠ ",
|
|
70721
|
+
overwriteCount,
|
|
70722
|
+
" selected ",
|
|
70723
|
+
overwriteCount === 1 ? "route" : "routes",
|
|
70724
|
+
" already exist in the cloud and will be overwritten. New routes are added; others are kept."
|
|
70725
|
+
] }),
|
|
70726
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-2.5 border-b border-surface-800 flex items-center justify-between text-xs flex-shrink-0", children: [
|
|
70727
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-400", children: [
|
|
70728
|
+
selected.size,
|
|
70729
|
+
" of ",
|
|
70730
|
+
routes.length,
|
|
70731
|
+
" routes selected"
|
|
70732
|
+
] }),
|
|
70733
|
+
routes.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
70734
|
+
"button",
|
|
70735
|
+
{
|
|
70736
|
+
onClick: () => setSelected(allSelected ? /* @__PURE__ */ new Set() : new Set(routes.map((r) => r.id))),
|
|
70737
|
+
className: "text-blue-400 hover:text-blue-300",
|
|
70738
|
+
children: allSelected ? "Deselect all" : "Select all"
|
|
70739
|
+
}
|
|
70740
|
+
)
|
|
70741
|
+
] }),
|
|
70742
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto px-2 py-2", children: routes.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-surface-500 text-xs px-2 py-6 text-center", children: "This mock has no routes." }) : routes.map((r) => /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-center gap-2 px-2 py-1.5 rounded hover:bg-surface-800/50 cursor-pointer text-xs", children: [
|
|
70743
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "checkbox", checked: selected.has(r.id), onChange: () => toggle(r.id), className: "accent-blue-500" }),
|
|
70744
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono font-semibold w-14 flex-shrink-0", style: { color: getMethodColor(r.method) }, children: r.method }),
|
|
70745
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-surface-300 truncate", children: r.path }),
|
|
70746
|
+
isExisting(r) && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[9px] uppercase tracking-wider text-amber-400 border border-amber-800/50 rounded px-1 py-0.5 flex-shrink-0", children: "in cloud" }),
|
|
70747
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-auto text-surface-500 flex-shrink-0", children: r.statusCode })
|
|
70748
|
+
] }, r.id)) }),
|
|
70749
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-4 py-3 border-t border-surface-800 flex items-center gap-2 flex-shrink-0", children: status.state === "ok" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
70750
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-green-400 text-[11px] flex-1 truncate", children: [
|
|
70751
|
+
"✓ Pushed ",
|
|
70752
|
+
selected.size,
|
|
70753
|
+
" route",
|
|
70754
|
+
selected.size !== 1 ? "s" : "",
|
|
70755
|
+
" → ",
|
|
70756
|
+
status.msg
|
|
70757
|
+
] }),
|
|
70758
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "px-4 py-1.5 bg-blue-600 hover:bg-blue-500 rounded text-xs font-medium", children: "Done" })
|
|
70759
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
70760
|
+
status.state === "err" && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-red-400 text-[11px] flex-1 truncate", children: [
|
|
70761
|
+
"✗ ",
|
|
70762
|
+
status.msg
|
|
70763
|
+
] }),
|
|
70764
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
70765
|
+
"button",
|
|
70766
|
+
{
|
|
70767
|
+
onClick: push2,
|
|
70768
|
+
disabled: status.state === "pushing" || selected.size === 0,
|
|
70769
|
+
className: "ml-auto px-4 py-1.5 bg-blue-600 hover:bg-blue-500 disabled:opacity-40 rounded text-xs font-medium",
|
|
70770
|
+
children: status.state === "pushing" ? "Pushing…" : overwriteCount > 0 ? `Push ${selected.size} (${addCount} new, ${overwriteCount} overwrite)` : `Push ${selected.size} route${selected.size !== 1 ? "s" : ""}`
|
|
70771
|
+
}
|
|
70772
|
+
),
|
|
70773
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "px-4 py-1.5 bg-surface-800 hover:bg-surface-700 rounded text-xs", children: "Cancel" })
|
|
70774
|
+
] }) })
|
|
70775
|
+
]
|
|
70776
|
+
}
|
|
70777
|
+
);
|
|
70778
|
+
}
|
|
70779
|
+
const { electron: electron$7 } = window;
|
|
69540
70780
|
function MockPanel() {
|
|
70781
|
+
const [pushTarget, setPushTarget] = reactExports.useState(null);
|
|
69541
70782
|
const mocks = useStore((s) => s.mocks);
|
|
69542
70783
|
const activeMockId = useStore((s) => s.activeMockId);
|
|
69543
70784
|
const setActiveMock = useStore((s) => s.setActiveMockId);
|
|
@@ -69565,15 +70806,15 @@ function MockPanel() {
|
|
|
69565
70806
|
setWsdlImporting(true);
|
|
69566
70807
|
try {
|
|
69567
70808
|
const existingPorts = mockList.map((m) => m.data.port);
|
|
69568
|
-
const { mock } = await electron$
|
|
70809
|
+
const { mock } = await electron$7.wsdlImport({ url: wsdlUrl.trim(), existingMockPorts: existingPorts });
|
|
69569
70810
|
const relPath = `mocks/${mock.id}.mock.json`;
|
|
69570
70811
|
loadMock(relPath, mock);
|
|
69571
|
-
await electron$
|
|
70812
|
+
await electron$7.saveMock(relPath, mock);
|
|
69572
70813
|
const ws2 = useStore.getState().workspace;
|
|
69573
70814
|
if (ws2) {
|
|
69574
70815
|
if (!ws2.mocks) ws2.mocks = [];
|
|
69575
70816
|
ws2.mocks.push(relPath);
|
|
69576
|
-
await electron$
|
|
70817
|
+
await electron$7.saveWorkspace(ws2);
|
|
69577
70818
|
}
|
|
69578
70819
|
setActiveMock(mock.id);
|
|
69579
70820
|
setWsdlOpen(false);
|
|
@@ -69587,12 +70828,12 @@ function MockPanel() {
|
|
|
69587
70828
|
async function handleAddMock() {
|
|
69588
70829
|
addMock();
|
|
69589
70830
|
const ws2 = useStore.getState().workspace;
|
|
69590
|
-
if (ws2) await electron$
|
|
70831
|
+
if (ws2) await electron$7.saveWorkspace(ws2);
|
|
69591
70832
|
const state = useStore.getState();
|
|
69592
70833
|
const newId = state.activeMockId;
|
|
69593
70834
|
if (newId) {
|
|
69594
70835
|
const entry = state.mocks[newId];
|
|
69595
|
-
await electron$
|
|
70836
|
+
await electron$7.saveMock(entry.relPath, entry.data);
|
|
69596
70837
|
setActiveMock(newId);
|
|
69597
70838
|
}
|
|
69598
70839
|
}
|
|
@@ -69600,15 +70841,15 @@ function MockPanel() {
|
|
|
69600
70841
|
e.stopPropagation();
|
|
69601
70842
|
const entry = useStore.getState().mocks[mockId];
|
|
69602
70843
|
if (!entry) return;
|
|
69603
|
-
if (entry.running) await electron$
|
|
70844
|
+
if (entry.running) await electron$7.mockStop(mockId);
|
|
69604
70845
|
deleteMock(mockId);
|
|
69605
70846
|
const ws2 = useStore.getState().workspace;
|
|
69606
|
-
if (ws2) await electron$
|
|
70847
|
+
if (ws2) await electron$7.saveWorkspace(ws2);
|
|
69607
70848
|
}
|
|
69608
70849
|
async function handleStartRecorder() {
|
|
69609
70850
|
setRecorderError("");
|
|
69610
70851
|
try {
|
|
69611
|
-
await electron$
|
|
70852
|
+
await electron$7.recordStart({ upstream: recorderUpstream, port: recorderPort });
|
|
69612
70853
|
setRecorderRunning(true);
|
|
69613
70854
|
} catch (err) {
|
|
69614
70855
|
setRecorderError(err instanceof Error ? err.message : String(err));
|
|
@@ -69620,18 +70861,19 @@ function MockPanel() {
|
|
|
69620
70861
|
if (!entry) return;
|
|
69621
70862
|
try {
|
|
69622
70863
|
if (entry.running) {
|
|
69623
|
-
await electron$
|
|
70864
|
+
await electron$7.mockStop(mockId);
|
|
69624
70865
|
setRunning(mockId, false);
|
|
69625
70866
|
} else {
|
|
69626
70867
|
const latest2 = useStore.getState().mocks[mockId].data;
|
|
69627
|
-
await electron$
|
|
69628
|
-
await electron$
|
|
70868
|
+
await electron$7.saveMock(entry.relPath, latest2);
|
|
70869
|
+
await electron$7.mockStart(latest2);
|
|
69629
70870
|
setRunning(mockId, true);
|
|
69630
70871
|
}
|
|
69631
70872
|
} catch {
|
|
69632
70873
|
}
|
|
69633
70874
|
}
|
|
69634
70875
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col flex-1 min-h-0", children: [
|
|
70876
|
+
pushTarget && /* @__PURE__ */ jsxRuntimeExports.jsx(PushToCloudModal, { mock: pushTarget, onClose: () => setPushTarget(null) }),
|
|
69635
70877
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-b border-surface-800 flex-shrink-0", children: [
|
|
69636
70878
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
69637
70879
|
"button",
|
|
@@ -69793,6 +71035,18 @@ function MockPanel() {
|
|
|
69793
71035
|
children: entry.running ? "■" : "▶"
|
|
69794
71036
|
}
|
|
69795
71037
|
),
|
|
71038
|
+
cloudEnabled() && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
71039
|
+
"button",
|
|
71040
|
+
{
|
|
71041
|
+
onClick: (e) => {
|
|
71042
|
+
e.stopPropagation();
|
|
71043
|
+
setPushTarget(mock);
|
|
71044
|
+
},
|
|
71045
|
+
className: "text-[10px] px-1 py-0.5 rounded text-surface-500 hover:text-blue-400 opacity-0 group-hover:opacity-100 transition-colors",
|
|
71046
|
+
title: "Push to cloud (choose routes)",
|
|
71047
|
+
children: "☁"
|
|
71048
|
+
}
|
|
71049
|
+
),
|
|
69796
71050
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
69797
71051
|
"button",
|
|
69798
71052
|
{
|
|
@@ -69810,7 +71064,7 @@ function MockPanel() {
|
|
|
69810
71064
|
}) })
|
|
69811
71065
|
] });
|
|
69812
71066
|
}
|
|
69813
|
-
const { electron: electron$
|
|
71067
|
+
const { electron: electron$6 } = window;
|
|
69814
71068
|
const METHODS_PLUS_ANY = ["ANY", "GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "QUERY"];
|
|
69815
71069
|
function RouteRow({
|
|
69816
71070
|
route,
|
|
@@ -70207,25 +71461,26 @@ function MockDetailPanel({ mockId }) {
|
|
|
70207
71461
|
const [error2, setError] = reactExports.useState(null);
|
|
70208
71462
|
const [newRouteId, setNewRouteId] = reactExports.useState(null);
|
|
70209
71463
|
const [activeTab, setActiveTab] = reactExports.useState("routes");
|
|
71464
|
+
const [showPush, setShowPush] = reactExports.useState(false);
|
|
70210
71465
|
if (!entry) return null;
|
|
70211
71466
|
const { data: mock, running } = entry;
|
|
70212
71467
|
const routes = mock.routes ?? [];
|
|
70213
71468
|
async function save(updated) {
|
|
70214
71469
|
updateMock(mock.id, updated);
|
|
70215
|
-
await electron$
|
|
70216
|
-
if (running) await electron$
|
|
70217
|
-
if (workspace) await electron$
|
|
71470
|
+
await electron$6.saveMock(entry.relPath, updated);
|
|
71471
|
+
if (running) await electron$6.mockUpdateRoutes(mock.id, updated.routes ?? []);
|
|
71472
|
+
if (workspace) await electron$6.saveWorkspace(workspace);
|
|
70218
71473
|
}
|
|
70219
71474
|
async function toggleRunning() {
|
|
70220
71475
|
setError(null);
|
|
70221
71476
|
try {
|
|
70222
71477
|
if (running) {
|
|
70223
|
-
await electron$
|
|
71478
|
+
await electron$6.mockStop(mock.id);
|
|
70224
71479
|
setRunning(mock.id, false);
|
|
70225
71480
|
} else {
|
|
70226
71481
|
const latest2 = useStore.getState().mocks[mock.id].data;
|
|
70227
|
-
await electron$
|
|
70228
|
-
await electron$
|
|
71482
|
+
await electron$6.saveMock(entry.relPath, latest2);
|
|
71483
|
+
await electron$6.mockStart(latest2);
|
|
70229
71484
|
setRunning(mock.id, true);
|
|
70230
71485
|
}
|
|
70231
71486
|
} catch (e) {
|
|
@@ -70316,10 +71571,20 @@ function MockDetailPanel({ mockId }) {
|
|
|
70316
71571
|
}
|
|
70317
71572
|
),
|
|
70318
71573
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ml-auto flex items-center gap-2", children: [
|
|
71574
|
+
showPush && /* @__PURE__ */ jsxRuntimeExports.jsx(PushToCloudModal, { mock, onClose: () => setShowPush(false) }),
|
|
70319
71575
|
error2 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-red-400 max-w-xs truncate", title: error2, children: [
|
|
70320
71576
|
"⚠ ",
|
|
70321
71577
|
error2
|
|
70322
71578
|
] }),
|
|
71579
|
+
cloudEnabled() && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
71580
|
+
"button",
|
|
71581
|
+
{
|
|
71582
|
+
onClick: () => setShowPush(true),
|
|
71583
|
+
className: "px-3 py-1.5 rounded text-sm font-medium bg-surface-800 hover:bg-surface-700 text-surface-300 border border-surface-700",
|
|
71584
|
+
title: "Push this mock to API Spector Cloud (choose routes)",
|
|
71585
|
+
children: "☁ Push to cloud"
|
|
71586
|
+
}
|
|
71587
|
+
),
|
|
70323
71588
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative group/cli flex items-center", children: [
|
|
70324
71589
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
70325
71590
|
"button",
|
|
@@ -70338,7 +71603,7 @@ function MockDetailPanel({ mockId }) {
|
|
|
70338
71603
|
"button",
|
|
70339
71604
|
{
|
|
70340
71605
|
onClick: () => {
|
|
70341
|
-
if (running) electron$
|
|
71606
|
+
if (running) electron$6.mockStop(mock.id);
|
|
70342
71607
|
deleteMock(mock.id);
|
|
70343
71608
|
setActive2(null);
|
|
70344
71609
|
},
|
|
@@ -70405,7 +71670,7 @@ function MockDetailPanel({ mockId }) {
|
|
|
70405
71670
|
] })
|
|
70406
71671
|
] });
|
|
70407
71672
|
}
|
|
70408
|
-
const { electron: electron$
|
|
71673
|
+
const { electron: electron$5 } = window;
|
|
70409
71674
|
function statusColor$1(status) {
|
|
70410
71675
|
if (status === 0) return "text-yellow-400";
|
|
70411
71676
|
if (status < 300) return "text-emerald-400";
|
|
@@ -70438,7 +71703,7 @@ function RecorderPanel({ onImportMock, onClose, defaultTargetMockId }) {
|
|
|
70438
71703
|
const upstream = useStore((s) => s.recorderUpstream);
|
|
70439
71704
|
const mockList = Object.values(useStore((s) => s.mocks));
|
|
70440
71705
|
reactExports.useEffect(() => {
|
|
70441
|
-
electron$
|
|
71706
|
+
electron$5.onRecordHit((entry) => {
|
|
70442
71707
|
setEntries((prev) => {
|
|
70443
71708
|
const next = [...prev, entry];
|
|
70444
71709
|
setTimeout(() => {
|
|
@@ -70448,12 +71713,12 @@ function RecorderPanel({ onImportMock, onClose, defaultTargetMockId }) {
|
|
|
70448
71713
|
});
|
|
70449
71714
|
});
|
|
70450
71715
|
return () => {
|
|
70451
|
-
electron$
|
|
71716
|
+
electron$5.offRecordHit();
|
|
70452
71717
|
};
|
|
70453
71718
|
}, []);
|
|
70454
71719
|
async function handleStop() {
|
|
70455
71720
|
try {
|
|
70456
|
-
const s = await electron$
|
|
71721
|
+
const s = await electron$5.recordStop();
|
|
70457
71722
|
setSession(s);
|
|
70458
71723
|
setStopped(true);
|
|
70459
71724
|
} catch {
|
|
@@ -70649,6 +71914,467 @@ function HeadersTable({ headers }) {
|
|
|
70649
71914
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-300 break-all", children: v })
|
|
70650
71915
|
] }, k)) });
|
|
70651
71916
|
}
|
|
71917
|
+
function kvToHeaders(kv) {
|
|
71918
|
+
const out = {};
|
|
71919
|
+
for (const p2 of kv ?? []) {
|
|
71920
|
+
if (p2.enabled === false || !p2.key) continue;
|
|
71921
|
+
out[p2.key] = p2.value;
|
|
71922
|
+
}
|
|
71923
|
+
return out;
|
|
71924
|
+
}
|
|
71925
|
+
function designContractToMock(cc, port = 4100) {
|
|
71926
|
+
const routes = cc.interactions.map((it, i) => ({
|
|
71927
|
+
id: it.id || `route-${i}`,
|
|
71928
|
+
// Pact path templates use {id}; the mock router uses :id.
|
|
71929
|
+
method: (it.request.method || "GET").toUpperCase(),
|
|
71930
|
+
path: (it.request.path || "/").replace(/\{([^}]+)\}/g, ":$1"),
|
|
71931
|
+
statusCode: it.response.status,
|
|
71932
|
+
headers: { "Content-Type": "application/json", ...kvToHeaders(it.response.headers) },
|
|
71933
|
+
body: it.response.body?.trim() ? it.response.body : "",
|
|
71934
|
+
description: it.description || void 0
|
|
71935
|
+
}));
|
|
71936
|
+
return {
|
|
71937
|
+
version: "1.0",
|
|
71938
|
+
id: `mock-${cc.id}`,
|
|
71939
|
+
name: `${cc.consumer} → ${cc.provider} (contract mock)`,
|
|
71940
|
+
port,
|
|
71941
|
+
routes
|
|
71942
|
+
};
|
|
71943
|
+
}
|
|
71944
|
+
const { electron: electron$4 } = window;
|
|
71945
|
+
function uid() {
|
|
71946
|
+
try {
|
|
71947
|
+
return crypto.randomUUID();
|
|
71948
|
+
} catch {
|
|
71949
|
+
return `id-${Date.now()}-${Math.floor(performance.now())}`;
|
|
71950
|
+
}
|
|
71951
|
+
}
|
|
71952
|
+
function newInteraction() {
|
|
71953
|
+
return {
|
|
71954
|
+
id: uid(),
|
|
71955
|
+
description: "get a resource",
|
|
71956
|
+
request: { method: "GET", path: "/resource/{id}", headers: [] },
|
|
71957
|
+
response: { status: 200, body: '{\n "id": 1\n}' }
|
|
71958
|
+
};
|
|
71959
|
+
}
|
|
71960
|
+
function newContract() {
|
|
71961
|
+
return { id: uid(), consumer: "my-consumer", provider: "my-provider", interactions: [newInteraction()] };
|
|
71962
|
+
}
|
|
71963
|
+
function KVRows({ label, rows, onChange, keyPlaceholder = "name", valuePlaceholder = "value" }) {
|
|
71964
|
+
const list2 = rows ?? [];
|
|
71965
|
+
const set2 = (i, patch) => onChange(list2.map((r, j) => j === i ? { ...r, ...patch } : r));
|
|
71966
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
71967
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase tracking-wider text-surface-500", children: label }),
|
|
71968
|
+
list2.map((r, i) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
71969
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
71970
|
+
"input",
|
|
71971
|
+
{
|
|
71972
|
+
value: r.key,
|
|
71973
|
+
onChange: (e) => set2(i, { key: e.target.value }),
|
|
71974
|
+
placeholder: keyPlaceholder,
|
|
71975
|
+
spellCheck: false,
|
|
71976
|
+
className: "flex-1 min-w-0 text-[11px] font-mono bg-surface-800 border border-surface-700 rounded px-2 py-1 focus:outline-none focus:border-blue-500"
|
|
71977
|
+
}
|
|
71978
|
+
),
|
|
71979
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
71980
|
+
"input",
|
|
71981
|
+
{
|
|
71982
|
+
value: r.value,
|
|
71983
|
+
onChange: (e) => set2(i, { value: e.target.value }),
|
|
71984
|
+
placeholder: valuePlaceholder,
|
|
71985
|
+
spellCheck: false,
|
|
71986
|
+
className: "flex-1 min-w-0 text-[11px] font-mono bg-surface-800 border border-surface-700 rounded px-2 py-1 focus:outline-none focus:border-blue-500"
|
|
71987
|
+
}
|
|
71988
|
+
),
|
|
71989
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => onChange(list2.filter((_, j) => j !== i)), className: "text-surface-600 hover:text-red-400 text-xs px-0.5", title: "Remove", children: "✕" })
|
|
71990
|
+
] }, i)),
|
|
71991
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => onChange([...list2, { key: "", value: "", enabled: true }]), className: "self-start text-[11px] text-blue-400 hover:text-blue-300", children: "+ add" })
|
|
71992
|
+
] });
|
|
71993
|
+
}
|
|
71994
|
+
function ContractDesignerModal({ onClose }) {
|
|
71995
|
+
const workspace = useStore((s) => s.workspace);
|
|
71996
|
+
const workspacePath = useStore((s) => s.workspacePath);
|
|
71997
|
+
const setWorkspace = useStore((s) => s.setWorkspace);
|
|
71998
|
+
const addMock = useStore((s) => s.addMock);
|
|
71999
|
+
const updateMock = useStore((s) => s.updateMock);
|
|
72000
|
+
const cloudConnected = useStore((s) => Boolean(s.workspace?.settings?.cloud?.enabled));
|
|
72001
|
+
const { toast, show } = useToast();
|
|
72002
|
+
const contracts = workspace?.designContracts ?? [];
|
|
72003
|
+
const [selectedId, setSelectedId] = reactExports.useState(contracts[0]?.id ?? null);
|
|
72004
|
+
const [version, setVersion] = reactExports.useState("0.1.0");
|
|
72005
|
+
const [busy, setBusy] = reactExports.useState(false);
|
|
72006
|
+
const selected = contracts.find((c) => c.id === selectedId) ?? null;
|
|
72007
|
+
async function persist(next) {
|
|
72008
|
+
if (!workspace) return;
|
|
72009
|
+
const updated = { ...workspace, designContracts: next };
|
|
72010
|
+
setWorkspace(updated, workspacePath ?? "");
|
|
72011
|
+
try {
|
|
72012
|
+
await electron$4.saveWorkspace(updated);
|
|
72013
|
+
} catch (e) {
|
|
72014
|
+
show(e.message, false);
|
|
72015
|
+
}
|
|
72016
|
+
}
|
|
72017
|
+
function upsert(contract) {
|
|
72018
|
+
const stamped = { ...contract, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
72019
|
+
const exists = contracts.some((c) => c.id === contract.id);
|
|
72020
|
+
persist(exists ? contracts.map((c) => c.id === contract.id ? stamped : c) : [...contracts, stamped]);
|
|
72021
|
+
}
|
|
72022
|
+
function addContract() {
|
|
72023
|
+
const c = newContract();
|
|
72024
|
+
setSelectedId(c.id);
|
|
72025
|
+
persist([...contracts, c]);
|
|
72026
|
+
}
|
|
72027
|
+
function deleteContract(id2) {
|
|
72028
|
+
const next = contracts.filter((c) => c.id !== id2);
|
|
72029
|
+
if (selectedId === id2) setSelectedId(next[0]?.id ?? null);
|
|
72030
|
+
persist(next);
|
|
72031
|
+
}
|
|
72032
|
+
function patchInteraction(ix, patch) {
|
|
72033
|
+
if (!selected) return;
|
|
72034
|
+
const interactions = selected.interactions.map((it, i) => i === ix ? { ...it, ...patch } : it);
|
|
72035
|
+
upsert({ ...selected, interactions });
|
|
72036
|
+
}
|
|
72037
|
+
async function saveLocally() {
|
|
72038
|
+
if (!selected) return;
|
|
72039
|
+
try {
|
|
72040
|
+
const relPath = await electron$4.exportDesignPact(selected);
|
|
72041
|
+
if (relPath) show(`Saved ${relPath} in the workspace`, true);
|
|
72042
|
+
} catch (e) {
|
|
72043
|
+
show(e.message, false);
|
|
72044
|
+
}
|
|
72045
|
+
}
|
|
72046
|
+
async function createMock() {
|
|
72047
|
+
if (!selected) return;
|
|
72048
|
+
try {
|
|
72049
|
+
addMock();
|
|
72050
|
+
const st = useStore.getState();
|
|
72051
|
+
const id2 = st.activeMockId;
|
|
72052
|
+
const entry = id2 ? st.mocks[id2] : null;
|
|
72053
|
+
if (!id2 || !entry) {
|
|
72054
|
+
show("Could not create the mock — open a workspace first.", false);
|
|
72055
|
+
return;
|
|
72056
|
+
}
|
|
72057
|
+
const mock = { ...designContractToMock(selected), id: id2, name: `${selected.consumer} → ${selected.provider} (contract mock)` };
|
|
72058
|
+
updateMock(id2, mock);
|
|
72059
|
+
await electron$4.saveMock(entry.relPath, mock);
|
|
72060
|
+
const ws2 = useStore.getState().workspace;
|
|
72061
|
+
if (ws2) await electron$4.saveWorkspace(ws2);
|
|
72062
|
+
show(`Created mock with ${mock.routes.length} route${mock.routes.length === 1 ? "" : "s"} — open the Mocks panel to run it`, true);
|
|
72063
|
+
} catch (e) {
|
|
72064
|
+
show(e.message, false);
|
|
72065
|
+
}
|
|
72066
|
+
}
|
|
72067
|
+
async function publish() {
|
|
72068
|
+
if (!selected) return;
|
|
72069
|
+
setBusy(true);
|
|
72070
|
+
try {
|
|
72071
|
+
const res = await electron$4.cloudPushDesignContract({ contract: selected, consumerVersion: version });
|
|
72072
|
+
const v = res.verification;
|
|
72073
|
+
if (v && !v.success) {
|
|
72074
|
+
const failed = v.checks.filter((c) => !c.passed).map((c) => c.interaction).join(", ");
|
|
72075
|
+
show(`Published, but bi-directional check failed: ${failed || "see matrix"}`, false);
|
|
72076
|
+
} else {
|
|
72077
|
+
show(`Published ${selected.consumer}@${version} to the cloud`, true);
|
|
72078
|
+
}
|
|
72079
|
+
} catch (e) {
|
|
72080
|
+
show(e.message, false);
|
|
72081
|
+
} finally {
|
|
72082
|
+
setBusy(false);
|
|
72083
|
+
}
|
|
72084
|
+
}
|
|
72085
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
72086
|
+
Modal,
|
|
72087
|
+
{
|
|
72088
|
+
onClose,
|
|
72089
|
+
title: "Contract Designer",
|
|
72090
|
+
subtitle: "Design a consumer-driven contract up front — no endpoint required — then publish it to API Spector Cloud.",
|
|
72091
|
+
panelClassName: "bg-surface-900 border border-surface-700 rounded-xl w-[min(1000px,94vw)] h-[min(760px,90vh)] flex flex-col",
|
|
72092
|
+
children: [
|
|
72093
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 min-h-0", children: [
|
|
72094
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-56 shrink-0 border-r border-surface-800 flex flex-col", children: [
|
|
72095
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-2 border-b border-surface-800 flex items-center justify-between", children: [
|
|
72096
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase tracking-wider text-surface-500 font-semibold", children: "Contracts" }),
|
|
72097
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: addContract, className: "text-xs text-blue-400 hover:text-blue-300", title: "New contract", children: "+ New" })
|
|
72098
|
+
] }),
|
|
72099
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
72100
|
+
contracts.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "px-3 py-3 text-xs text-surface-500", children: [
|
|
72101
|
+
"No contracts yet. Click ",
|
|
72102
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-blue-400", children: "+ New" }),
|
|
72103
|
+
"."
|
|
72104
|
+
] }),
|
|
72105
|
+
contracts.map((c) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
72106
|
+
"button",
|
|
72107
|
+
{
|
|
72108
|
+
onClick: () => setSelectedId(c.id),
|
|
72109
|
+
className: `w-full text-left px-3 py-2 border-b border-surface-800/60 transition-colors ${c.id === selectedId ? "bg-surface-800" : "hover:bg-surface-800/50"}`,
|
|
72110
|
+
children: [
|
|
72111
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-surface-200 truncate", children: [
|
|
72112
|
+
c.consumer,
|
|
72113
|
+
" ",
|
|
72114
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600", children: "→" }),
|
|
72115
|
+
" ",
|
|
72116
|
+
c.provider
|
|
72117
|
+
] }),
|
|
72118
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[10px] text-surface-500", children: [
|
|
72119
|
+
c.interactions.length,
|
|
72120
|
+
" interaction",
|
|
72121
|
+
c.interactions.length === 1 ? "" : "s"
|
|
72122
|
+
] })
|
|
72123
|
+
]
|
|
72124
|
+
},
|
|
72125
|
+
c.id
|
|
72126
|
+
))
|
|
72127
|
+
] })
|
|
72128
|
+
] }),
|
|
72129
|
+
!selected ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex items-center justify-center text-surface-500 text-sm", children: "Select or create a contract." }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col min-h-0", children: [
|
|
72130
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-4 py-3 border-b border-surface-800 flex flex-wrap items-end gap-3", children: [
|
|
72131
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
72132
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase tracking-wider text-surface-500", children: "Consumer" }),
|
|
72133
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72134
|
+
"input",
|
|
72135
|
+
{
|
|
72136
|
+
value: selected.consumer,
|
|
72137
|
+
onChange: (e) => upsert({ ...selected, consumer: e.target.value }),
|
|
72138
|
+
className: "text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1 w-44 focus:outline-none focus:border-blue-500"
|
|
72139
|
+
}
|
|
72140
|
+
)
|
|
72141
|
+
] }),
|
|
72142
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 pb-1.5", children: "→" }),
|
|
72143
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
72144
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase tracking-wider text-surface-500", children: "Provider" }),
|
|
72145
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72146
|
+
"input",
|
|
72147
|
+
{
|
|
72148
|
+
value: selected.provider,
|
|
72149
|
+
onChange: (e) => upsert({ ...selected, provider: e.target.value }),
|
|
72150
|
+
className: "text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1 w-44 focus:outline-none focus:border-blue-500"
|
|
72151
|
+
}
|
|
72152
|
+
)
|
|
72153
|
+
] }),
|
|
72154
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ml-auto flex items-end gap-2", children: [
|
|
72155
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
72156
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase tracking-wider text-surface-500", children: "Version" }),
|
|
72157
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72158
|
+
"input",
|
|
72159
|
+
{
|
|
72160
|
+
value: version,
|
|
72161
|
+
onChange: (e) => setVersion(e.target.value),
|
|
72162
|
+
className: "text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1 w-24 focus:outline-none focus:border-blue-500"
|
|
72163
|
+
}
|
|
72164
|
+
)
|
|
72165
|
+
] }),
|
|
72166
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72167
|
+
"button",
|
|
72168
|
+
{
|
|
72169
|
+
onClick: createMock,
|
|
72170
|
+
title: "Turn this contract into a runnable mock the consumer can develop against (no provider needed)",
|
|
72171
|
+
className: "px-3 py-1.5 text-xs border border-surface-600 text-surface-200 hover:border-blue-500 hover:text-white rounded transition-colors whitespace-nowrap",
|
|
72172
|
+
children: "Create mock"
|
|
72173
|
+
}
|
|
72174
|
+
),
|
|
72175
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72176
|
+
"button",
|
|
72177
|
+
{
|
|
72178
|
+
onClick: saveLocally,
|
|
72179
|
+
title: "Write the compiled pact to pacts/ in this workspace (git-committable, no cloud needed)",
|
|
72180
|
+
className: "px-3 py-1.5 text-xs border border-surface-600 text-surface-200 hover:border-blue-500 hover:text-white rounded transition-colors whitespace-nowrap",
|
|
72181
|
+
children: "Save to workspace"
|
|
72182
|
+
}
|
|
72183
|
+
),
|
|
72184
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72185
|
+
"button",
|
|
72186
|
+
{
|
|
72187
|
+
onClick: publish,
|
|
72188
|
+
disabled: busy || !cloudConnected,
|
|
72189
|
+
title: cloudConnected ? "Publish the compiled pact to API Spector Cloud" : "Connect to cloud in Settings → Cloud first",
|
|
72190
|
+
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",
|
|
72191
|
+
children: busy ? "Publishing…" : "Publish to Cloud"
|
|
72192
|
+
}
|
|
72193
|
+
),
|
|
72194
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72195
|
+
"button",
|
|
72196
|
+
{
|
|
72197
|
+
onClick: () => deleteContract(selected.id),
|
|
72198
|
+
className: "px-2 py-1.5 text-xs text-red-400 hover:bg-red-900/30 rounded transition-colors",
|
|
72199
|
+
children: "Delete"
|
|
72200
|
+
}
|
|
72201
|
+
)
|
|
72202
|
+
] })
|
|
72203
|
+
] }),
|
|
72204
|
+
!cloudConnected && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "px-4 py-1.5 text-[11px] text-amber-400 bg-amber-950/20 border-b border-surface-800", children: "Not connected to API Spector Cloud — connect in Settings → Cloud to publish. You can still design and save the contract." }),
|
|
72205
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-y-auto px-4 py-3 flex flex-col gap-4", children: [
|
|
72206
|
+
selected.interactions.map((it, ix) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border border-surface-800 rounded-lg p-3 flex flex-col gap-2.5", children: [
|
|
72207
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
72208
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72209
|
+
"input",
|
|
72210
|
+
{
|
|
72211
|
+
value: it.description,
|
|
72212
|
+
onChange: (e) => patchInteraction(ix, { description: e.target.value }),
|
|
72213
|
+
placeholder: "what this interaction is",
|
|
72214
|
+
className: "flex-1 text-xs font-medium bg-transparent border-b border-surface-800 focus:border-blue-500 focus:outline-none py-0.5"
|
|
72215
|
+
}
|
|
72216
|
+
),
|
|
72217
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72218
|
+
"button",
|
|
72219
|
+
{
|
|
72220
|
+
onClick: () => upsert({ ...selected, interactions: selected.interactions.filter((_, i) => i !== ix) }),
|
|
72221
|
+
className: "text-surface-600 hover:text-red-400 text-xs",
|
|
72222
|
+
title: "Remove interaction",
|
|
72223
|
+
children: "✕"
|
|
72224
|
+
}
|
|
72225
|
+
)
|
|
72226
|
+
] }),
|
|
72227
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
72228
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72229
|
+
"select",
|
|
72230
|
+
{
|
|
72231
|
+
value: it.request.method,
|
|
72232
|
+
onChange: (e) => patchInteraction(ix, { request: { ...it.request, method: e.target.value } }),
|
|
72233
|
+
className: "text-xs bg-surface-800 border border-surface-700 rounded px-1.5 py-1 focus:outline-none focus:border-blue-500",
|
|
72234
|
+
children: ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"].map((m) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { children: m }, m))
|
|
72235
|
+
}
|
|
72236
|
+
),
|
|
72237
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72238
|
+
"input",
|
|
72239
|
+
{
|
|
72240
|
+
value: it.request.path,
|
|
72241
|
+
onChange: (e) => patchInteraction(ix, { request: { ...it.request, path: e.target.value } }),
|
|
72242
|
+
placeholder: "/brands/{id}",
|
|
72243
|
+
className: "flex-1 text-xs font-mono bg-surface-800 border border-surface-700 rounded px-2 py-1 focus:outline-none focus:border-blue-500"
|
|
72244
|
+
}
|
|
72245
|
+
)
|
|
72246
|
+
] }),
|
|
72247
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72248
|
+
"input",
|
|
72249
|
+
{
|
|
72250
|
+
value: it.providerState ?? "",
|
|
72251
|
+
onChange: (e) => patchInteraction(ix, { providerState: e.target.value }),
|
|
72252
|
+
placeholder: 'provider state (e.g. "brand 1 exists") — optional',
|
|
72253
|
+
className: "text-xs bg-surface-800 border border-surface-700 rounded px-2 py-1 focus:outline-none focus:border-blue-500"
|
|
72254
|
+
}
|
|
72255
|
+
),
|
|
72256
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
72257
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2.5 border-r border-surface-800 pr-4", children: [
|
|
72258
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase tracking-wider text-surface-400 font-semibold", children: "Request" }),
|
|
72259
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72260
|
+
KVRows,
|
|
72261
|
+
{
|
|
72262
|
+
label: "Query params",
|
|
72263
|
+
rows: it.request.query,
|
|
72264
|
+
onChange: (q) => patchInteraction(ix, { request: { ...it.request, query: q } }),
|
|
72265
|
+
keyPlaceholder: "e.g. discontinued",
|
|
72266
|
+
valuePlaceholder: "true"
|
|
72267
|
+
}
|
|
72268
|
+
),
|
|
72269
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72270
|
+
KVRows,
|
|
72271
|
+
{
|
|
72272
|
+
label: "Headers",
|
|
72273
|
+
rows: it.request.headers,
|
|
72274
|
+
onChange: (h) => patchInteraction(ix, { request: { ...it.request, headers: h } }),
|
|
72275
|
+
keyPlaceholder: "Accept",
|
|
72276
|
+
valuePlaceholder: "application/json"
|
|
72277
|
+
}
|
|
72278
|
+
),
|
|
72279
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
72280
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase tracking-wider text-surface-500", children: "Body (JSON, optional)" }),
|
|
72281
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72282
|
+
"textarea",
|
|
72283
|
+
{
|
|
72284
|
+
value: it.request.body ?? "",
|
|
72285
|
+
onChange: (e) => patchInteraction(ix, { request: { ...it.request, body: e.target.value } }),
|
|
72286
|
+
rows: 3,
|
|
72287
|
+
placeholder: "{ }",
|
|
72288
|
+
spellCheck: false,
|
|
72289
|
+
className: "text-[11px] font-mono bg-surface-800 border border-surface-700 rounded px-2 py-1.5 focus:outline-none focus:border-blue-500 resize-y"
|
|
72290
|
+
}
|
|
72291
|
+
)
|
|
72292
|
+
] })
|
|
72293
|
+
] }),
|
|
72294
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2.5", children: [
|
|
72295
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] uppercase tracking-wider text-surface-400 font-semibold flex items-center gap-2", children: [
|
|
72296
|
+
"Expected response",
|
|
72297
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72298
|
+
"input",
|
|
72299
|
+
{
|
|
72300
|
+
type: "number",
|
|
72301
|
+
value: it.response.status,
|
|
72302
|
+
title: "expected status code",
|
|
72303
|
+
onChange: (e) => patchInteraction(ix, { response: { ...it.response, status: Number(e.target.value) || 0 } }),
|
|
72304
|
+
className: "w-16 text-[11px] bg-surface-900 border border-surface-700 rounded px-1 py-0.5 focus:outline-none focus:border-blue-500"
|
|
72305
|
+
}
|
|
72306
|
+
)
|
|
72307
|
+
] }),
|
|
72308
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72309
|
+
KVRows,
|
|
72310
|
+
{
|
|
72311
|
+
label: "Headers",
|
|
72312
|
+
rows: it.response.headers,
|
|
72313
|
+
onChange: (h) => patchInteraction(ix, { response: { ...it.response, headers: h } }),
|
|
72314
|
+
keyPlaceholder: "Content-Type",
|
|
72315
|
+
valuePlaceholder: "application/json"
|
|
72316
|
+
}
|
|
72317
|
+
),
|
|
72318
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
72319
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] uppercase tracking-wider text-surface-500", children: "Body" }),
|
|
72320
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72321
|
+
"textarea",
|
|
72322
|
+
{
|
|
72323
|
+
value: it.response.body ?? "",
|
|
72324
|
+
onChange: (e) => patchInteraction(ix, { response: { ...it.response, body: e.target.value } }),
|
|
72325
|
+
rows: 3,
|
|
72326
|
+
placeholder: "[{ id: string, name: string, slug: string }] — or a JSON example",
|
|
72327
|
+
spellCheck: false,
|
|
72328
|
+
className: "text-[11px] font-mono bg-surface-800 border border-surface-700 rounded px-2 py-1.5 focus:outline-none focus:border-blue-500 resize-y"
|
|
72329
|
+
}
|
|
72330
|
+
),
|
|
72331
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-surface-500 leading-relaxed", children: [
|
|
72332
|
+
"A JSON example (matched by type when the toggle is on), or a ",
|
|
72333
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-300", children: "type shape" }),
|
|
72334
|
+
" to check each property's type: ",
|
|
72335
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-surface-300", children: "string, number, integer, boolean, null" }),
|
|
72336
|
+
" plus nested ",
|
|
72337
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: "{ }" }),
|
|
72338
|
+
" / ",
|
|
72339
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: "[ ]" }),
|
|
72340
|
+
". E.g. ",
|
|
72341
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-surface-300", children: "[{ id: string, qty: integer }]" }),
|
|
72342
|
+
". Compiles to Pact ",
|
|
72343
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: "matchingRules" }),
|
|
72344
|
+
"."
|
|
72345
|
+
] })
|
|
72346
|
+
] })
|
|
72347
|
+
] })
|
|
72348
|
+
] }),
|
|
72349
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex items-center gap-2 text-[11px] text-surface-400", children: [
|
|
72350
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72351
|
+
"input",
|
|
72352
|
+
{
|
|
72353
|
+
type: "checkbox",
|
|
72354
|
+
checked: it.looseMatch !== false,
|
|
72355
|
+
onChange: (e) => patchInteraction(ix, { looseMatch: e.target.checked }),
|
|
72356
|
+
className: "accent-blue-500"
|
|
72357
|
+
}
|
|
72358
|
+
),
|
|
72359
|
+
"Match a JSON example by type, not exact value (tolerant — recommended)"
|
|
72360
|
+
] })
|
|
72361
|
+
] }, it.id)),
|
|
72362
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72363
|
+
"button",
|
|
72364
|
+
{
|
|
72365
|
+
onClick: () => upsert({ ...selected, interactions: [...selected.interactions, newInteraction()] }),
|
|
72366
|
+
className: "self-start text-xs text-blue-400 hover:text-blue-300",
|
|
72367
|
+
children: "+ Add interaction"
|
|
72368
|
+
}
|
|
72369
|
+
)
|
|
72370
|
+
] })
|
|
72371
|
+
] })
|
|
72372
|
+
] }),
|
|
72373
|
+
toast && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed bottom-4 right-4 z-[120] w-96", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Toast, { toast }) })
|
|
72374
|
+
]
|
|
72375
|
+
}
|
|
72376
|
+
);
|
|
72377
|
+
}
|
|
70652
72378
|
const { electron: electron$3 } = window;
|
|
70653
72379
|
function ContractPanel({ fuzzReport, setFuzzReport }) {
|
|
70654
72380
|
const collections = useStore((s) => s.collections);
|
|
@@ -70664,6 +72390,29 @@ function ContractPanel({ fuzzReport, setFuzzReport }) {
|
|
|
70664
72390
|
const removeContractSnapshot = useStore((s) => s.removeContractSnapshot);
|
|
70665
72391
|
const workspace = useStore((s) => s.workspace);
|
|
70666
72392
|
const [mode, setMode] = reactExports.useState("consumer");
|
|
72393
|
+
const [showDesigner, setShowDesigner] = reactExports.useState(false);
|
|
72394
|
+
const cloudConnected = useStore((s) => Boolean(s.workspace?.settings?.cloud?.enabled));
|
|
72395
|
+
const [providerName, setProviderName] = reactExports.useState("");
|
|
72396
|
+
const [specVersion, setSpecVersion] = reactExports.useState("");
|
|
72397
|
+
const [publishingSpec, setPublishingSpec] = reactExports.useState(false);
|
|
72398
|
+
const [publishNote, setPublishNote] = reactExports.useState(null);
|
|
72399
|
+
async function publishSpecToCloud() {
|
|
72400
|
+
setError(null);
|
|
72401
|
+
setPublishNote(null);
|
|
72402
|
+
setPublishingSpec(true);
|
|
72403
|
+
try {
|
|
72404
|
+
const res = await electron$3.cloudPushSpec({
|
|
72405
|
+
pacticipant: providerName.trim(),
|
|
72406
|
+
version: specVersion.trim(),
|
|
72407
|
+
specUrl: specUrl.trim()
|
|
72408
|
+
});
|
|
72409
|
+
setPublishNote(`Published ${providerName.trim()}@${specVersion.trim()} — ${res.verified_contracts} contract(s) re-verified`);
|
|
72410
|
+
} catch (e) {
|
|
72411
|
+
setError(e.message);
|
|
72412
|
+
} finally {
|
|
72413
|
+
setPublishingSpec(false);
|
|
72414
|
+
}
|
|
72415
|
+
}
|
|
70667
72416
|
const [specUrl, setSpecUrl] = reactExports.useState("");
|
|
70668
72417
|
const [requestBaseUrl, setRequestBaseUrl] = reactExports.useState("");
|
|
70669
72418
|
const [providerBaseUrl, setProviderBaseUrl] = reactExports.useState("");
|
|
@@ -70683,6 +72432,7 @@ function ContractPanel({ fuzzReport, setFuzzReport }) {
|
|
|
70683
72432
|
const contractRequests = allRequests.filter(
|
|
70684
72433
|
(r) => r.contract && (r.contract.statusCode !== void 0 || r.contract.bodySchema || r.contract.bodyMatcher || r.contract.headers?.length)
|
|
70685
72434
|
);
|
|
72435
|
+
const designInteractionCount = (workspace?.designContracts ?? []).reduce((n, cc) => n + cc.interactions.length, 0);
|
|
70686
72436
|
const isFuzz = mode === "fuzz";
|
|
70687
72437
|
const needsSpec = mode === "provider" || mode === "bidirectional";
|
|
70688
72438
|
const showSpec = needsSpec || isFuzz;
|
|
@@ -70709,6 +72459,9 @@ function ContractPanel({ fuzzReport, setFuzzReport }) {
|
|
|
70709
72459
|
const result = await electron$3.runContracts({
|
|
70710
72460
|
mode,
|
|
70711
72461
|
requests,
|
|
72462
|
+
// Let the main process add design-first contracts (Designer + pacts/) for
|
|
72463
|
+
// the contract-bearing modes, so they run without a manual pact-import.
|
|
72464
|
+
designContracts: workspace?.designContracts,
|
|
70712
72465
|
envVars,
|
|
70713
72466
|
collectionVars,
|
|
70714
72467
|
specUrl: specUrl.trim() || void 0,
|
|
@@ -70794,6 +72547,15 @@ function ContractPanel({ fuzzReport, setFuzzReport }) {
|
|
|
70794
72547
|
}
|
|
70795
72548
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col flex-1 min-h-0 overflow-hidden", children: [
|
|
70796
72549
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3 px-3 py-3 border-b border-surface-800 flex-shrink-0", children: [
|
|
72550
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72551
|
+
"button",
|
|
72552
|
+
{
|
|
72553
|
+
onClick: () => setShowDesigner(true),
|
|
72554
|
+
className: "flex items-center justify-center gap-1.5 text-xs px-3 py-1.5 rounded-lg border border-dashed border-surface-600 text-surface-300 hover:border-blue-500 hover:text-white transition-colors",
|
|
72555
|
+
title: "Design a consumer-driven contract up front, with no endpoints, then publish it to the cloud",
|
|
72556
|
+
children: "✎ Design a contract (no endpoint needed)"
|
|
72557
|
+
}
|
|
72558
|
+
),
|
|
70797
72559
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-1 bg-surface-800 rounded-lg p-0.5", children: [
|
|
70798
72560
|
["consumer", "Consumer"],
|
|
70799
72561
|
["provider", "Provider"],
|
|
@@ -70914,7 +72676,44 @@ function ContractPanel({ fuzzReport, setFuzzReport }) {
|
|
|
70914
72676
|
}
|
|
70915
72677
|
)
|
|
70916
72678
|
] }),
|
|
70917
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-600 mt-1 leading-relaxed", children: "Pin a snapshot to run against a specific spec version later, even after the provider ships an update." })
|
|
72679
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-surface-600 mt-1 leading-relaxed", children: "Pin a snapshot to run against a specific spec version later, even after the provider ships an update." }),
|
|
72680
|
+
cloudConnected && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 pt-2 border-t border-surface-800 flex flex-col gap-1.5", children: [
|
|
72681
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "text-[10px] text-surface-500 uppercase tracking-wider font-medium", children: [
|
|
72682
|
+
"Publish spec to cloud ",
|
|
72683
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 normal-case tracking-normal", children: "(provider side of bi-directional)" })
|
|
72684
|
+
] }),
|
|
72685
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-1", children: [
|
|
72686
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72687
|
+
"input",
|
|
72688
|
+
{
|
|
72689
|
+
value: providerName,
|
|
72690
|
+
onChange: (e) => setProviderName(e.target.value),
|
|
72691
|
+
placeholder: "provider name",
|
|
72692
|
+
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"
|
|
72693
|
+
}
|
|
72694
|
+
),
|
|
72695
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72696
|
+
"input",
|
|
72697
|
+
{
|
|
72698
|
+
value: specVersion,
|
|
72699
|
+
onChange: (e) => setSpecVersion(e.target.value),
|
|
72700
|
+
placeholder: "version (git SHA)",
|
|
72701
|
+
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 font-mono placeholder-surface-600"
|
|
72702
|
+
}
|
|
72703
|
+
),
|
|
72704
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72705
|
+
"button",
|
|
72706
|
+
{
|
|
72707
|
+
onClick: publishSpecToCloud,
|
|
72708
|
+
disabled: publishingSpec || !specUrl.trim() || !providerName.trim() || !specVersion.trim(),
|
|
72709
|
+
title: "Publish this OpenAPI spec to the broker; consumers' pacts are re-verified against it",
|
|
72710
|
+
className: "px-2.5 text-xs bg-blue-700 hover:bg-blue-600 disabled:bg-surface-800 disabled:text-surface-600 rounded transition-colors",
|
|
72711
|
+
children: publishingSpec ? "…" : "Publish"
|
|
72712
|
+
}
|
|
72713
|
+
)
|
|
72714
|
+
] }),
|
|
72715
|
+
publishNote && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] text-emerald-400 leading-relaxed", children: publishNote })
|
|
72716
|
+
] })
|
|
70918
72717
|
] }),
|
|
70919
72718
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
70920
72719
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "text-[10px] text-surface-500 uppercase tracking-wider font-medium block mb-1", children: [
|
|
@@ -71012,7 +72811,7 @@ function ContractPanel({ fuzzReport, setFuzzReport }) {
|
|
|
71012
72811
|
] })
|
|
71013
72812
|
] }),
|
|
71014
72813
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
71015
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-surface-500", children: mode === "provider" || isFuzz ? `${allRequests.length} request${allRequests.length !== 1 ? "s" : ""}` : `${contractRequests.length} contract${contractRequests.length !== 1 ? "s" : ""} defined` }),
|
|
72814
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-surface-500", children: mode === "provider" || isFuzz ? `${allRequests.length} request${allRequests.length !== 1 ? "s" : ""}` : `${contractRequests.length + designInteractionCount} contract${contractRequests.length + designInteractionCount !== 1 ? "s" : ""} defined` }),
|
|
71016
72815
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
71017
72816
|
"button",
|
|
71018
72817
|
{
|
|
@@ -71051,7 +72850,8 @@ function ContractPanel({ fuzzReport, setFuzzReport }) {
|
|
|
71051
72850
|
" cases"
|
|
71052
72851
|
] })
|
|
71053
72852
|
] })
|
|
71054
|
-
] })
|
|
72853
|
+
] }),
|
|
72854
|
+
showDesigner && /* @__PURE__ */ jsxRuntimeExports.jsx(ContractDesignerModal, { onClose: () => setShowDesigner(false) })
|
|
71055
72855
|
] });
|
|
71056
72856
|
}
|
|
71057
72857
|
function statusColor(code2) {
|
|
@@ -72010,7 +73810,7 @@ function CiTab() {
|
|
|
72010
73810
|
const [platform, setPlatform] = reactExports.useState("unknown");
|
|
72011
73811
|
const [envId, setEnvId] = reactExports.useState("");
|
|
72012
73812
|
const [tags2, setTags] = reactExports.useState("");
|
|
72013
|
-
const [
|
|
73813
|
+
const [preview2, setPreview] = reactExports.useState("");
|
|
72014
73814
|
const [written, setWritten] = reactExports.useState(false);
|
|
72015
73815
|
const [error2, setError] = reactExports.useState(null);
|
|
72016
73816
|
reactExports.useEffect(() => {
|
|
@@ -72032,7 +73832,7 @@ function CiTab() {
|
|
|
72032
73832
|
async function write() {
|
|
72033
73833
|
try {
|
|
72034
73834
|
setError(null);
|
|
72035
|
-
await electron$2.gitWriteCiFile(ciFilePath(platform),
|
|
73835
|
+
await electron$2.gitWriteCiFile(ciFilePath(platform), preview2);
|
|
72036
73836
|
setWritten(true);
|
|
72037
73837
|
} catch (e) {
|
|
72038
73838
|
setError(String(e));
|
|
@@ -72117,7 +73917,7 @@ function CiTab() {
|
|
|
72117
73917
|
] }),
|
|
72118
73918
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-auto", children: [
|
|
72119
73919
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "px-3 pt-2 pb-1 text-[10px] uppercase tracking-widest text-surface-600 font-semibold", children: "Preview" }),
|
|
72120
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "px-3 pb-3 text-[10px] font-mono text-surface-400 leading-relaxed whitespace-pre-wrap", children:
|
|
73920
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "px-3 pb-3 text-[10px] font-mono text-surface-400 leading-relaxed whitespace-pre-wrap", children: preview2 })
|
|
72121
73921
|
] })
|
|
72122
73922
|
] });
|
|
72123
73923
|
}
|
|
@@ -72498,6 +74298,7 @@ function App() {
|
|
|
72498
74298
|
const setCommandPaletteOpen = useStore((s) => s.setCommandPaletteOpen);
|
|
72499
74299
|
const setWsStatus = useStore((s) => s.setWsStatus);
|
|
72500
74300
|
const addWsMessage = useStore((s) => s.addWsMessage);
|
|
74301
|
+
const pushLiveStreamEvents = useStore((s) => s.pushLiveStreamEvents);
|
|
72501
74302
|
const [fuzzReport, setFuzzReport] = reactExports.useState(null);
|
|
72502
74303
|
const [sidebarOpen, setSidebarOpen] = reactExports.useState(true);
|
|
72503
74304
|
const [responseOpen, setResponseOpen] = reactExports.useState(false);
|
|
@@ -72548,6 +74349,12 @@ function App() {
|
|
|
72548
74349
|
});
|
|
72549
74350
|
return () => electron.offWsEvents();
|
|
72550
74351
|
}, [addWsMessage, setWsStatus]);
|
|
74352
|
+
reactExports.useEffect(() => {
|
|
74353
|
+
electron.onRequestStreamEvent(({ streamId, events }) => {
|
|
74354
|
+
pushLiveStreamEvents(streamId, events);
|
|
74355
|
+
});
|
|
74356
|
+
return () => electron.offRequestStreamEvent();
|
|
74357
|
+
}, [pushLiveStreamEvents]);
|
|
72551
74358
|
reactExports.useEffect(() => {
|
|
72552
74359
|
function handleKeyDown(e) {
|
|
72553
74360
|
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
|
@@ -72575,7 +74382,21 @@ function App() {
|
|
|
72575
74382
|
return map;
|
|
72576
74383
|
}, [collections]);
|
|
72577
74384
|
const activeTab = reactExports.useMemo(() => tabs.find((t2) => t2.id === activeTabId) ?? null, [tabs, activeTabId]);
|
|
72578
|
-
const
|
|
74385
|
+
const activeBaseRequest = activeTab?.requestId ? requestsById.get(activeTab.requestId) ?? null : null;
|
|
74386
|
+
const activeRequest = reactExports.useMemo(() => {
|
|
74387
|
+
if (!activeBaseRequest) return null;
|
|
74388
|
+
if (!activeTab?.exampleId) return activeBaseRequest;
|
|
74389
|
+
const ex = activeBaseRequest.examples?.find((e) => e.id === activeTab.exampleId);
|
|
74390
|
+
if (!ex) return activeBaseRequest;
|
|
74391
|
+
const o = ex.request ?? {};
|
|
74392
|
+
return {
|
|
74393
|
+
...activeBaseRequest,
|
|
74394
|
+
...o,
|
|
74395
|
+
params: o.params ?? [],
|
|
74396
|
+
headers: o.headers ?? [],
|
|
74397
|
+
body: o.body ?? { mode: "none" }
|
|
74398
|
+
};
|
|
74399
|
+
}, [activeBaseRequest, activeTab?.exampleId]);
|
|
72579
74400
|
const openTabContextMenu = reactExports.useCallback((tabId, x, y) => {
|
|
72580
74401
|
setTabContextMenu({ x, y, tabId });
|
|
72581
74402
|
}, []);
|
|
@@ -72600,7 +74421,7 @@ function App() {
|
|
|
72600
74421
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "#6aa3c8" }, children: "Spector" }),
|
|
72601
74422
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-2 text-[10px] font-normal opacity-50", children: [
|
|
72602
74423
|
"v",
|
|
72603
|
-
"0.4.
|
|
74424
|
+
"0.4.7"
|
|
72604
74425
|
] }),
|
|
72605
74426
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mx-2 opacity-30", children: "·" }),
|
|
72606
74427
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -72717,12 +74538,13 @@ function App() {
|
|
|
72717
74538
|
tabs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center border-b border-surface-800 bg-surface-950 flex-shrink-0", children: [
|
|
72718
74539
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center overflow-x-auto flex-1 min-w-0", children: tabs.map((tab) => {
|
|
72719
74540
|
const req = tab.requestId ? requestsById.get(tab.requestId) ?? null : null;
|
|
74541
|
+
const exampleName = tab.exampleId ? req?.examples?.find((e) => e.id === tab.exampleId)?.name : null;
|
|
72720
74542
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
72721
74543
|
TabRow,
|
|
72722
74544
|
{
|
|
72723
74545
|
tabId: tab.id,
|
|
72724
74546
|
method: req?.method,
|
|
72725
|
-
name: req?.name ?? "Untitled",
|
|
74547
|
+
name: exampleName ? `${req?.name ?? "Untitled"} · ${exampleName}` : req?.name ?? "Untitled",
|
|
72726
74548
|
isActive: tab.id === activeTabId,
|
|
72727
74549
|
onActivate: setActiveTabId,
|
|
72728
74550
|
onClose: closeTab,
|