@testsmith/api-spector 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/main/chunks/{broker-client-DqDgA2G6.js → broker-client-Cl6Fu3oD.js} +1 -1
- package/out/main/chunks/{handle-_4XMUlwm.js → handle-HQp1EXf8.js} +33 -1
- package/out/main/chunks/{import-ujxXe3Uu.js → import-DVpFH9Wb.js} +2 -2
- package/out/main/chunks/{perf-run-Ww_weuqI.js → perf-run-BNunvZsG.js} +1 -1
- package/out/main/chunks/{request-exec-CcF1Fzve.js → request-exec-B8DJ8Id2.js} +24 -18
- package/out/main/chunks/{soap-handler-BF5ii0UV.js → soap-handler-D_Hj9e8S.js} +2 -2
- package/out/main/contract.js +3 -3
- package/out/main/flow.js +3 -3
- package/out/main/index.js +35 -11
- package/out/main/lib.js +2 -2
- package/out/main/perf-worker.js +3 -3
- package/out/main/perf.js +4 -4
- package/out/main/register-handlers.js +217 -5
- package/out/main/runner.js +3 -3
- package/out/main/wsdl.js +3 -3
- package/out/preload/index.js +58 -1
- package/out/renderer/assets/{GraphQLEditor-CmfodipY.js → GraphQLEditor-RRDuQogA.js} +1 -1
- package/out/renderer/assets/{SoapEditor-CVRCFvJy.js → SoapEditor-BncNQmjP.js} +1 -1
- package/out/renderer/assets/index--T34lt1s.css +627 -0
- package/out/renderer/assets/{index-BV1FsSQR.js → index-C6_D_4og.js} +981 -228
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
- package/out/renderer/assets/index-D9e_KYf1.css +0 -627
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./GraphQLEditor-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./GraphQLEditor-RRDuQogA.js","./codemirror-BKmwMUlV.js","./ajv-CJPwFjiP.js","./SoapEditor-BncNQmjP.js"])))=>i.map(i=>d[i]);
|
|
2
2
|
import { r as requireReact, g as getDefaultExportFromCjs, R as React, a as reactExports, b as autocompletion, h as hoverTooltip, j as jsxRuntimeExports, V as ViewPlugin, E as EditorView, k as keymap, t as toggleComment, D as Decoration, c as RangeSetBuilder, x as xml, d as json, e as ReactCodeMirror, o as oneDark, f as javascript } from "./codemirror-BKmwMUlV.js";
|
|
3
3
|
import { r as requireAjv } from "./ajv-CJPwFjiP.js";
|
|
4
4
|
var client = { exports: {} };
|
|
@@ -14771,7 +14771,7 @@ const useStore$1 = create$1()(
|
|
|
14771
14771
|
})
|
|
14772
14772
|
}))
|
|
14773
14773
|
);
|
|
14774
|
-
const { electron: electron$
|
|
14774
|
+
const { electron: electron$J } = window;
|
|
14775
14775
|
function useAutoSave() {
|
|
14776
14776
|
const collections = useStore$1((s) => s.collections);
|
|
14777
14777
|
useStore$1((s) => s.environments);
|
|
@@ -14790,7 +14790,7 @@ function useAutoSave() {
|
|
|
14790
14790
|
for (const { relPath, data, dirty } of dirtyCollections) {
|
|
14791
14791
|
if (!dirty) continue;
|
|
14792
14792
|
try {
|
|
14793
|
-
await electron$
|
|
14793
|
+
await electron$J.saveCollection(relPath, data);
|
|
14794
14794
|
markCollectionClean(data.id);
|
|
14795
14795
|
} catch (e) {
|
|
14796
14796
|
console.error("Auto-save failed for", relPath, e);
|
|
@@ -14809,7 +14809,7 @@ function useAutoSave() {
|
|
|
14809
14809
|
for (const { relPath, data, dirty } of dirtyFlows) {
|
|
14810
14810
|
if (!dirty) continue;
|
|
14811
14811
|
try {
|
|
14812
|
-
await electron$
|
|
14812
|
+
await electron$J.saveFlow(relPath, data);
|
|
14813
14813
|
markFlowClean(data.id);
|
|
14814
14814
|
} catch (e) {
|
|
14815
14815
|
console.error("Auto-save failed for", relPath, e);
|
|
@@ -14825,7 +14825,7 @@ function useAutoSave() {
|
|
|
14825
14825
|
if (wsTimerRef.current) clearTimeout(wsTimerRef.current);
|
|
14826
14826
|
wsTimerRef.current = setTimeout(async () => {
|
|
14827
14827
|
try {
|
|
14828
|
-
await electron$
|
|
14828
|
+
await electron$J.saveWorkspace(workspace);
|
|
14829
14829
|
} catch {
|
|
14830
14830
|
}
|
|
14831
14831
|
}, 300);
|
|
@@ -14834,7 +14834,7 @@ function useAutoSave() {
|
|
|
14834
14834
|
};
|
|
14835
14835
|
}, [workspace]);
|
|
14836
14836
|
}
|
|
14837
|
-
const { electron: electron$
|
|
14837
|
+
const { electron: electron$I } = window;
|
|
14838
14838
|
function useWorkspaceLoader() {
|
|
14839
14839
|
const loadCollection = useStore$1((s) => s.loadCollection);
|
|
14840
14840
|
const loadEnvironment = useStore$1((s) => s.loadEnvironment);
|
|
@@ -14861,7 +14861,7 @@ function useWorkspaceLoader() {
|
|
|
14861
14861
|
if (typeof ws.settings?.zoom === "number") setZoom(ws.settings.zoom);
|
|
14862
14862
|
if (ws.settings?.persistHistory) {
|
|
14863
14863
|
try {
|
|
14864
|
-
const entries = await electron$
|
|
14864
|
+
const entries = await electron$I.loadHistory();
|
|
14865
14865
|
useStore$1.getState().setHistory(entries);
|
|
14866
14866
|
} catch {
|
|
14867
14867
|
}
|
|
@@ -14870,14 +14870,14 @@ function useWorkspaceLoader() {
|
|
|
14870
14870
|
}
|
|
14871
14871
|
for (const colPath of ws.collections ?? []) {
|
|
14872
14872
|
try {
|
|
14873
|
-
const col = await electron$
|
|
14873
|
+
const col = await electron$I.loadCollection(colPath);
|
|
14874
14874
|
loadCollection(colPath, col);
|
|
14875
14875
|
} catch {
|
|
14876
14876
|
}
|
|
14877
14877
|
}
|
|
14878
14878
|
for (const envPath of ws.environments ?? []) {
|
|
14879
14879
|
try {
|
|
14880
|
-
const env2 = await electron$
|
|
14880
|
+
const env2 = await electron$I.loadEnvironment(envPath);
|
|
14881
14881
|
loadEnvironment(envPath, env2);
|
|
14882
14882
|
} catch {
|
|
14883
14883
|
}
|
|
@@ -14896,32 +14896,38 @@ function useWorkspaceLoader() {
|
|
|
14896
14896
|
}
|
|
14897
14897
|
for (const relPath of ws.mocks ?? []) {
|
|
14898
14898
|
try {
|
|
14899
|
-
const mockData = await electron$
|
|
14899
|
+
const mockData = await electron$I.loadMock(relPath);
|
|
14900
14900
|
loadMock(relPath, mockData);
|
|
14901
14901
|
} catch {
|
|
14902
14902
|
}
|
|
14903
14903
|
}
|
|
14904
14904
|
for (const relPath of ws.flows ?? []) {
|
|
14905
14905
|
try {
|
|
14906
|
-
const flowData = await electron$
|
|
14906
|
+
const flowData = await electron$I.loadFlow(relPath);
|
|
14907
14907
|
loadFlow(relPath, flowData);
|
|
14908
14908
|
} catch {
|
|
14909
14909
|
}
|
|
14910
14910
|
}
|
|
14911
14911
|
try {
|
|
14912
|
-
const snapshots = await electron$
|
|
14912
|
+
const snapshots = await electron$I.listContractSnapshots(ws.contracts ?? []);
|
|
14913
14913
|
for (const { relPath, snapshot } of snapshots) loadContractSnapshot(relPath, snapshot);
|
|
14914
14914
|
} catch {
|
|
14915
14915
|
}
|
|
14916
14916
|
if ((ws.collections ?? []).length > 0) {
|
|
14917
14917
|
try {
|
|
14918
|
-
const firstCol = await electron$
|
|
14918
|
+
const firstCol = await electron$I.loadCollection(ws.collections[0]);
|
|
14919
14919
|
setActiveCollection(firstCol.id);
|
|
14920
14920
|
} catch {
|
|
14921
14921
|
}
|
|
14922
14922
|
}
|
|
14923
14923
|
}, [loadCollection, loadEnvironment, loadMock, loadFlow, loadContractSnapshot, setActiveCollection, setTheme, setZoom]);
|
|
14924
|
-
|
|
14924
|
+
const reloadWorkspace = reactExports.useCallback(async () => {
|
|
14925
|
+
const path = useStore$1.getState().workspacePath;
|
|
14926
|
+
if (!path) return;
|
|
14927
|
+
const result = await electron$I.openWorkspacePath(path);
|
|
14928
|
+
if (result) await applyWorkspace(result.workspace, result.workspacePath);
|
|
14929
|
+
}, [applyWorkspace]);
|
|
14930
|
+
return { applyWorkspace, reloadWorkspace };
|
|
14925
14931
|
}
|
|
14926
14932
|
var reactDomExports = requireReactDom();
|
|
14927
14933
|
const ReactDOM = /* @__PURE__ */ getDefaultExportFromCjs(reactDomExports);
|
|
@@ -15985,6 +15991,7 @@ function useVarValues() {
|
|
|
15985
15991
|
}
|
|
15986
15992
|
return result;
|
|
15987
15993
|
}
|
|
15994
|
+
const Workspace = "Workspace";
|
|
15988
15995
|
const Collections$6 = "Collections";
|
|
15989
15996
|
const History$6 = "History";
|
|
15990
15997
|
const Git$6 = "Git";
|
|
@@ -16190,6 +16197,9 @@ const or$6 = "or";
|
|
|
16190
16197
|
const Disabled$6 = "Disabled";
|
|
16191
16198
|
const en = {
|
|
16192
16199
|
"Close tab": "Close tab",
|
|
16200
|
+
"Open api-spector.dev": "Open api-spector.dev",
|
|
16201
|
+
Workspace,
|
|
16202
|
+
"API Spector home": "API Spector home",
|
|
16193
16203
|
"Request body": "Request body",
|
|
16194
16204
|
"Script editor": "Script editor",
|
|
16195
16205
|
"JSON schema": "JSON schema",
|
|
@@ -25857,7 +25867,7 @@ function Modal({
|
|
|
25857
25867
|
}
|
|
25858
25868
|
);
|
|
25859
25869
|
}
|
|
25860
|
-
const { electron: electron$
|
|
25870
|
+
const { electron: electron$H } = window;
|
|
25861
25871
|
function Oauth2Form({ auth, onChange }) {
|
|
25862
25872
|
const t = useT();
|
|
25863
25873
|
const activeEnv = useActiveEnvironment();
|
|
@@ -25877,7 +25887,7 @@ function Oauth2Form({ auth, onChange }) {
|
|
|
25877
25887
|
const flow = auth.oauth2Flow ?? "client_credentials";
|
|
25878
25888
|
async function saveSecret(ref) {
|
|
25879
25889
|
if (!secretValue || !ref) return;
|
|
25880
|
-
await electron$
|
|
25890
|
+
await electron$H.setSecret(ref, secretValue);
|
|
25881
25891
|
setSaved(true);
|
|
25882
25892
|
setSecretValue("");
|
|
25883
25893
|
setTimeout(() => setSaved(false), 2e3);
|
|
@@ -25886,7 +25896,7 @@ function Oauth2Form({ auth, onChange }) {
|
|
|
25886
25896
|
setStatus("fetching");
|
|
25887
25897
|
setError("");
|
|
25888
25898
|
try {
|
|
25889
|
-
const result = await electron$
|
|
25899
|
+
const result = await electron$H.oauth2StartFlow(auth, resolveCtx());
|
|
25890
25900
|
onChange({ oauth2CachedToken: result.accessToken, oauth2TokenExpiry: result.expiresAt });
|
|
25891
25901
|
if (result.refreshToken) setRefreshToken(result.refreshToken);
|
|
25892
25902
|
setStatus("ok");
|
|
@@ -25900,7 +25910,7 @@ function Oauth2Form({ auth, onChange }) {
|
|
|
25900
25910
|
setStatus("fetching");
|
|
25901
25911
|
setError("");
|
|
25902
25912
|
try {
|
|
25903
|
-
const result = await electron$
|
|
25913
|
+
const result = await electron$H.oauth2RefreshToken(auth, resolveCtx(), refreshToken);
|
|
25904
25914
|
onChange({ oauth2CachedToken: result.accessToken, oauth2TokenExpiry: result.expiresAt });
|
|
25905
25915
|
if (result.refreshToken) setRefreshToken(result.refreshToken);
|
|
25906
25916
|
setStatus("ok");
|
|
@@ -26760,7 +26770,7 @@ function CollectionSettingsModal({ collection: collection2, onClose }) {
|
|
|
26760
26770
|
}
|
|
26761
26771
|
);
|
|
26762
26772
|
}
|
|
26763
|
-
const { electron: electron$
|
|
26773
|
+
const { electron: electron$G } = window;
|
|
26764
26774
|
function normalisePath(url) {
|
|
26765
26775
|
let path = url.replace(/^\{\{[^}]+\}\}/, "").replace(/^https?:\/\/[^/]+/, "");
|
|
26766
26776
|
if (!path.startsWith("/")) path = "/" + path;
|
|
@@ -26848,7 +26858,7 @@ function SchemaSyncModal({
|
|
|
26848
26858
|
setLoading(true);
|
|
26849
26859
|
setError(null);
|
|
26850
26860
|
try {
|
|
26851
|
-
const entries = await electron$
|
|
26861
|
+
const entries = await electron$G.extractOpenApiSchemas();
|
|
26852
26862
|
if (!entries) {
|
|
26853
26863
|
setLoading(false);
|
|
26854
26864
|
return;
|
|
@@ -26867,7 +26877,7 @@ function SchemaSyncModal({
|
|
|
26867
26877
|
setLoading(true);
|
|
26868
26878
|
setError(null);
|
|
26869
26879
|
try {
|
|
26870
|
-
const entries = await electron$
|
|
26880
|
+
const entries = await electron$G.extractOpenApiSchemasFromUrl(trimmed);
|
|
26871
26881
|
setSpecEntries(entries);
|
|
26872
26882
|
autoSelectChanged(entries);
|
|
26873
26883
|
} catch (err) {
|
|
@@ -26900,7 +26910,7 @@ function SchemaSyncModal({
|
|
|
26900
26910
|
}
|
|
26901
26911
|
const entry = useStore$1.getState().collections[collectionId];
|
|
26902
26912
|
if (entry) {
|
|
26903
|
-
await electron$
|
|
26913
|
+
await electron$G.saveCollection(entry.relPath, entry.data);
|
|
26904
26914
|
markCollectionClean(collectionId);
|
|
26905
26915
|
}
|
|
26906
26916
|
onClose();
|
|
@@ -27413,7 +27423,7 @@ function hasContract(r) {
|
|
|
27413
27423
|
const c = r.contract;
|
|
27414
27424
|
return !!c && (c.statusCode != null || !!c.bodySchema || !!c.bodyMatcher || (c.headers?.length ?? 0) > 0 || (c.providerStates?.length ?? 0) > 0);
|
|
27415
27425
|
}
|
|
27416
|
-
const { electron: electron$
|
|
27426
|
+
const { electron: electron$F } = window;
|
|
27417
27427
|
function cloudEnabled() {
|
|
27418
27428
|
return Boolean(useStore$1.getState().workspace?.settings?.cloud?.enabled);
|
|
27419
27429
|
}
|
|
@@ -27422,7 +27432,7 @@ function assertEnabled() {
|
|
|
27422
27432
|
}
|
|
27423
27433
|
async function pushContractToCloud(requests, opts) {
|
|
27424
27434
|
assertEnabled();
|
|
27425
|
-
return electron$
|
|
27435
|
+
return electron$F.cloudPushPact({
|
|
27426
27436
|
consumer: opts.consumer,
|
|
27427
27437
|
provider: opts.provider,
|
|
27428
27438
|
consumerVersion: opts.version,
|
|
@@ -27431,16 +27441,16 @@ async function pushContractToCloud(requests, opts) {
|
|
|
27431
27441
|
}
|
|
27432
27442
|
async function pushProviderSpecToCloud(opts) {
|
|
27433
27443
|
assertEnabled();
|
|
27434
|
-
return electron$
|
|
27444
|
+
return electron$F.cloudPushSpec(opts);
|
|
27435
27445
|
}
|
|
27436
27446
|
function openCloudMatrix() {
|
|
27437
|
-
void electron$
|
|
27447
|
+
void electron$F.cloudOpenMatrix();
|
|
27438
27448
|
}
|
|
27439
27449
|
async function pushFlowToCloud(flow) {
|
|
27440
27450
|
assertEnabled();
|
|
27441
27451
|
const s = useStore$1.getState();
|
|
27442
27452
|
const environment = resolveEnvironmentById(s.environments, s.activeEnvironmentId);
|
|
27443
|
-
return electron$
|
|
27453
|
+
return electron$F.cloudPushFlow({
|
|
27444
27454
|
flow,
|
|
27445
27455
|
collections: Object.values(s.collections).map((c) => c.data),
|
|
27446
27456
|
flows: Object.values(s.flows).map((f) => f.data),
|
|
@@ -27450,12 +27460,12 @@ async function pushFlowToCloud(flow) {
|
|
|
27450
27460
|
}
|
|
27451
27461
|
async function runFlowInCloud(flow, onStatus) {
|
|
27452
27462
|
assertEnabled();
|
|
27453
|
-
const started = await electron$
|
|
27463
|
+
const started = await electron$F.cloudRunFlow(flow.name);
|
|
27454
27464
|
onStatus?.(started.status);
|
|
27455
27465
|
const deadlineMs = 2 * 60 * 1e3;
|
|
27456
27466
|
const t0 = Date.now();
|
|
27457
27467
|
for (; ; ) {
|
|
27458
|
-
const run = await electron$
|
|
27468
|
+
const run = await electron$F.cloudGetFlowRun({ name: flow.name, runId: started.id });
|
|
27459
27469
|
onStatus?.(run.status);
|
|
27460
27470
|
if (run.status === "passed" || run.status === "failed" || run.status === "error" || run.status === "done") {
|
|
27461
27471
|
if (run.summary) return run.summary;
|
|
@@ -27466,12 +27476,53 @@ async function runFlowInCloud(flow, onStatus) {
|
|
|
27466
27476
|
}
|
|
27467
27477
|
}
|
|
27468
27478
|
function openCloudFlow(flow) {
|
|
27469
|
-
void electron$
|
|
27479
|
+
void electron$F.cloudOpenFlow(flow.name);
|
|
27480
|
+
}
|
|
27481
|
+
async function shareCollectionToCloud(collection2) {
|
|
27482
|
+
assertEnabled();
|
|
27483
|
+
return electron$F.cloudShareCollection(collection2);
|
|
27484
|
+
}
|
|
27485
|
+
async function shareRequestToCloud(request2) {
|
|
27486
|
+
assertEnabled();
|
|
27487
|
+
return electron$F.cloudShareRequest(request2);
|
|
27488
|
+
}
|
|
27489
|
+
function collectFolderRequestIds(folder2) {
|
|
27490
|
+
return [...folder2.requestIds, ...folder2.folders.flatMap(collectFolderRequestIds)];
|
|
27491
|
+
}
|
|
27492
|
+
async function shareFolderToCloud(collection2, folder2) {
|
|
27493
|
+
assertEnabled();
|
|
27494
|
+
const ids = new Set(collectFolderRequestIds(folder2));
|
|
27495
|
+
const requests = {};
|
|
27496
|
+
for (const id2 of ids) {
|
|
27497
|
+
const r = collection2.requests[id2];
|
|
27498
|
+
if (r) requests[id2] = r;
|
|
27499
|
+
}
|
|
27500
|
+
const payload = {
|
|
27501
|
+
version: "1.0",
|
|
27502
|
+
id: folder2.id,
|
|
27503
|
+
name: folder2.name,
|
|
27504
|
+
rootFolder: folder2,
|
|
27505
|
+
requests,
|
|
27506
|
+
collectionVariables: collection2.collectionVariables
|
|
27507
|
+
};
|
|
27508
|
+
return electron$F.cloudShareFolder({ sourceId: folder2.id, name: folder2.name, payload });
|
|
27509
|
+
}
|
|
27510
|
+
async function lookupShare(type, sourceId) {
|
|
27511
|
+
assertEnabled();
|
|
27512
|
+
return electron$F.cloudShareLookup({ type, sourceId });
|
|
27513
|
+
}
|
|
27514
|
+
async function restrictShare(token, expiresDays) {
|
|
27515
|
+
assertEnabled();
|
|
27516
|
+
return electron$F.cloudShareUpdate({ token, expiresDays });
|
|
27517
|
+
}
|
|
27518
|
+
async function revokeShare(token) {
|
|
27519
|
+
assertEnabled();
|
|
27520
|
+
await electron$F.cloudShareRevoke(token);
|
|
27470
27521
|
}
|
|
27471
27522
|
async function getCloudMockRoutes(name) {
|
|
27472
27523
|
if (!cloudEnabled()) return null;
|
|
27473
27524
|
try {
|
|
27474
|
-
const res = await electron$
|
|
27525
|
+
const res = await electron$F.cloudGetMock(name);
|
|
27475
27526
|
return res.exists ? res.routes ?? [] : null;
|
|
27476
27527
|
} catch {
|
|
27477
27528
|
return null;
|
|
@@ -27480,7 +27531,7 @@ async function getCloudMockRoutes(name) {
|
|
|
27480
27531
|
async function pushMockToCloud(server, routeIds) {
|
|
27481
27532
|
assertEnabled();
|
|
27482
27533
|
const routes = routeIds ? (server.routes ?? []).filter((r) => routeIds.includes(r.id)) : server.routes ?? [];
|
|
27483
|
-
return electron$
|
|
27534
|
+
return electron$F.cloudPushMock({ ...server, routes });
|
|
27484
27535
|
}
|
|
27485
27536
|
async function pushRequestAsMonitor(request2, opts) {
|
|
27486
27537
|
assertEnabled();
|
|
@@ -27504,7 +27555,7 @@ async function pushRequestAsMonitor(request2, opts) {
|
|
|
27504
27555
|
...request2.headers
|
|
27505
27556
|
];
|
|
27506
27557
|
const mergedRequest = { ...request2, auth: mergedAuth, headers: mergedHeaders };
|
|
27507
|
-
return electron$
|
|
27558
|
+
return electron$F.cloudPushMonitor(
|
|
27508
27559
|
{
|
|
27509
27560
|
request: mergedRequest,
|
|
27510
27561
|
setup,
|
|
@@ -27922,6 +27973,201 @@ function Toast({ toast }) {
|
|
|
27922
27973
|
if (!toast) return null;
|
|
27923
27974
|
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 });
|
|
27924
27975
|
}
|
|
27976
|
+
function CloudRequiredModal({
|
|
27977
|
+
action,
|
|
27978
|
+
onConnect,
|
|
27979
|
+
onClose
|
|
27980
|
+
}) {
|
|
27981
|
+
const t = useT();
|
|
27982
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
27983
|
+
Modal,
|
|
27984
|
+
{
|
|
27985
|
+
onClose,
|
|
27986
|
+
closeOnBackdrop: true,
|
|
27987
|
+
overlayClassName: "bg-black/50 z-[300] flex items-center justify-center",
|
|
27988
|
+
panelClassName: "bg-surface-900 border border-surface-700 rounded-lg shadow-2xl p-5 w-96 flex flex-col gap-4",
|
|
27989
|
+
children: [
|
|
27990
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
27991
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "shrink-0 w-10 h-10 rounded-full bg-sky-900/40 border border-sky-700/40 flex items-center justify-center text-sky-300", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z" }) }) }),
|
|
27992
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
27993
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-sm font-semibold text-white", children: t("Connect to API Spector Cloud") }),
|
|
27994
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-400 mt-0.5", children: t("Sharing needs the cloud") })
|
|
27995
|
+
] })
|
|
27996
|
+
] }),
|
|
27997
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-surface-300 leading-relaxed", children: action ? t("To :action you need to connect this workspace to API Spector Cloud, which hosts the public link.", { action }) : t("Public share links are hosted in API Spector Cloud. Connect this workspace to the cloud to create one.") }),
|
|
27998
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-500", children: t("Only request definitions with {{variables}} are shared. Secrets and environment values are never uploaded.") }),
|
|
27999
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
28000
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28001
|
+
"button",
|
|
28002
|
+
{
|
|
28003
|
+
onClick: onClose,
|
|
28004
|
+
className: "px-3 py-1.5 text-xs text-surface-400 hover:text-white transition-colors",
|
|
28005
|
+
children: t("Not now")
|
|
28006
|
+
}
|
|
28007
|
+
),
|
|
28008
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28009
|
+
"button",
|
|
28010
|
+
{
|
|
28011
|
+
onClick: onConnect,
|
|
28012
|
+
className: "px-3 py-1.5 text-xs font-medium text-white bg-sky-700 hover:bg-sky-600 rounded transition-colors",
|
|
28013
|
+
children: t("Open Cloud settings")
|
|
28014
|
+
}
|
|
28015
|
+
)
|
|
28016
|
+
] })
|
|
28017
|
+
]
|
|
28018
|
+
}
|
|
28019
|
+
);
|
|
28020
|
+
}
|
|
28021
|
+
function ShareModal({
|
|
28022
|
+
title,
|
|
28023
|
+
type,
|
|
28024
|
+
sourceId,
|
|
28025
|
+
onCreate,
|
|
28026
|
+
onClose
|
|
28027
|
+
}) {
|
|
28028
|
+
const t = useT();
|
|
28029
|
+
const [loading, setLoading] = reactExports.useState(true);
|
|
28030
|
+
const [busy, setBusy] = reactExports.useState(false);
|
|
28031
|
+
const [error2, setError] = reactExports.useState(null);
|
|
28032
|
+
const [copied, setCopied] = reactExports.useState(false);
|
|
28033
|
+
const [live, setLive] = reactExports.useState(null);
|
|
28034
|
+
const [expiryDays, setExpiryDays] = reactExports.useState(0);
|
|
28035
|
+
reactExports.useEffect(() => {
|
|
28036
|
+
let cancelled = false;
|
|
28037
|
+
(async () => {
|
|
28038
|
+
try {
|
|
28039
|
+
const res = await lookupShare(type, sourceId);
|
|
28040
|
+
if (!cancelled && res.exists && res.token && res.url && res.deep_link) {
|
|
28041
|
+
setLive({ token: res.token, url: res.url, deep_link: res.deep_link, expires_at: res.expires_at ?? null });
|
|
28042
|
+
}
|
|
28043
|
+
} catch (e) {
|
|
28044
|
+
if (!cancelled) setError(e.message);
|
|
28045
|
+
} finally {
|
|
28046
|
+
if (!cancelled) setLoading(false);
|
|
28047
|
+
}
|
|
28048
|
+
})();
|
|
28049
|
+
return () => {
|
|
28050
|
+
cancelled = true;
|
|
28051
|
+
};
|
|
28052
|
+
}, [type, sourceId]);
|
|
28053
|
+
async function run(fn) {
|
|
28054
|
+
setBusy(true);
|
|
28055
|
+
setError(null);
|
|
28056
|
+
try {
|
|
28057
|
+
await fn();
|
|
28058
|
+
} catch (e) {
|
|
28059
|
+
setError(e.message);
|
|
28060
|
+
} finally {
|
|
28061
|
+
setBusy(false);
|
|
28062
|
+
}
|
|
28063
|
+
}
|
|
28064
|
+
const create2 = () => run(async () => {
|
|
28065
|
+
const r = await onCreate();
|
|
28066
|
+
setLive({ token: r.token, url: r.url, deep_link: r.deep_link, expires_at: r.expires_at ?? null });
|
|
28067
|
+
});
|
|
28068
|
+
const applyExpiry = () => run(async () => {
|
|
28069
|
+
if (!live) return;
|
|
28070
|
+
const r = await restrictShare(live.token, expiryDays);
|
|
28071
|
+
setLive({ ...live, expires_at: r.expires_at ?? null });
|
|
28072
|
+
});
|
|
28073
|
+
const revoke = () => run(async () => {
|
|
28074
|
+
if (!live) return;
|
|
28075
|
+
await revokeShare(live.token);
|
|
28076
|
+
setLive(null);
|
|
28077
|
+
});
|
|
28078
|
+
const copy2 = async () => {
|
|
28079
|
+
if (!live) return;
|
|
28080
|
+
try {
|
|
28081
|
+
await navigator.clipboard.writeText(live.url);
|
|
28082
|
+
setCopied(true);
|
|
28083
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
28084
|
+
} catch {
|
|
28085
|
+
}
|
|
28086
|
+
};
|
|
28087
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28088
|
+
Modal,
|
|
28089
|
+
{
|
|
28090
|
+
onClose,
|
|
28091
|
+
title: t("Share: :name", { name: title }),
|
|
28092
|
+
overlayClassName: "bg-black/50 z-[300] flex items-center justify-center",
|
|
28093
|
+
panelClassName: "bg-surface-900 border border-surface-700 rounded-lg shadow-2xl w-[32rem] max-w-[92vw] flex flex-col",
|
|
28094
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-5 flex flex-col gap-4", children: [
|
|
28095
|
+
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-red-400 bg-red-900/30 border border-red-800/40 rounded px-2 py-1.5", children: error2 }),
|
|
28096
|
+
loading ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-surface-400", children: t("Checking share status…") }) : !live ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
28097
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-surface-300 leading-relaxed", children: type === "request" ? t("Create a public read-only link to this request. Anyone with the link can view it or import it into their own app.") : type === "folder" ? t("Create a public read-only link to this folder. Anyone with the link can view its requests or import them into their own app.") : t("Create a public read-only link to this collection. Anyone with the link can view it or import it into their own app.") }),
|
|
28098
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-500", children: t("Only request definitions with {{variables}} are shared. Secrets and environment values are never uploaded.") }),
|
|
28099
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28100
|
+
"button",
|
|
28101
|
+
{
|
|
28102
|
+
onClick: create2,
|
|
28103
|
+
disabled: busy,
|
|
28104
|
+
className: "px-3 py-1.5 text-xs font-medium text-white bg-sky-700 hover:bg-sky-600 disabled:opacity-50 rounded transition-colors",
|
|
28105
|
+
children: busy ? t("Creating…") : t("Create public link")
|
|
28106
|
+
}
|
|
28107
|
+
) })
|
|
28108
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
28109
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
28110
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-[11px] uppercase tracking-wide text-surface-500", children: t("Public link") }),
|
|
28111
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex items-center gap-2", children: [
|
|
28112
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28113
|
+
"input",
|
|
28114
|
+
{
|
|
28115
|
+
readOnly: true,
|
|
28116
|
+
value: live.url,
|
|
28117
|
+
onClick: (e) => e.target.select(),
|
|
28118
|
+
className: "flex-1 rounded bg-surface-950 border border-surface-700 px-2 py-1.5 text-xs font-mono text-surface-200"
|
|
28119
|
+
}
|
|
28120
|
+
),
|
|
28121
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: copy2, className: "px-3 py-1.5 text-xs border border-surface-700 rounded text-surface-300 hover:text-white transition-colors", children: copied ? t("Copied") : t("Copy") })
|
|
28122
|
+
] })
|
|
28123
|
+
] }),
|
|
28124
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-end gap-2", children: [
|
|
28125
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
|
|
28126
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-[11px] uppercase tracking-wide text-surface-500", children: t("Restrict") }),
|
|
28127
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-400 mt-1", children: live.expires_at ? t("Expires :date", { date: new Date(live.expires_at).toLocaleString() }) : t("Never expires") })
|
|
28128
|
+
] }),
|
|
28129
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
28130
|
+
"select",
|
|
28131
|
+
{
|
|
28132
|
+
value: expiryDays,
|
|
28133
|
+
onChange: (e) => setExpiryDays(Number(e.target.value)),
|
|
28134
|
+
className: "rounded bg-surface-950 border border-surface-700 px-2 py-1.5 text-xs text-surface-200",
|
|
28135
|
+
children: [
|
|
28136
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: 0, children: t("No expiry") }),
|
|
28137
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: 1, children: t("1 day") }),
|
|
28138
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: 7, children: t("7 days") }),
|
|
28139
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: 30, children: t("30 days") })
|
|
28140
|
+
]
|
|
28141
|
+
}
|
|
28142
|
+
),
|
|
28143
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28144
|
+
"button",
|
|
28145
|
+
{
|
|
28146
|
+
onClick: applyExpiry,
|
|
28147
|
+
disabled: busy,
|
|
28148
|
+
className: "px-3 py-1.5 text-xs border border-surface-700 rounded text-surface-300 hover:text-white disabled:opacity-50 transition-colors",
|
|
28149
|
+
children: t("Apply")
|
|
28150
|
+
}
|
|
28151
|
+
)
|
|
28152
|
+
] }),
|
|
28153
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-500", children: t("Only request definitions with {{variables}} are shared. Secrets and environment values are never uploaded.") }),
|
|
28154
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center pt-2 border-t border-surface-800", children: [
|
|
28155
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28156
|
+
"button",
|
|
28157
|
+
{
|
|
28158
|
+
onClick: revoke,
|
|
28159
|
+
disabled: busy,
|
|
28160
|
+
className: "px-3 py-1.5 text-xs text-red-400 hover:text-red-300 disabled:opacity-50 transition-colors",
|
|
28161
|
+
children: t("Revoke link")
|
|
28162
|
+
}
|
|
28163
|
+
),
|
|
28164
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "px-3 py-1.5 text-xs text-surface-400 hover:text-white transition-colors", children: t("Done") })
|
|
28165
|
+
] })
|
|
28166
|
+
] })
|
|
28167
|
+
] })
|
|
28168
|
+
}
|
|
28169
|
+
);
|
|
28170
|
+
}
|
|
27925
28171
|
function requestPath(url) {
|
|
27926
28172
|
const trimmed = url.trim().replace(/^\{\{[^}]+\}\}/, "").replace(/^https?:\/\/[^/]+/i, "");
|
|
27927
28173
|
return trimmed || url.trim();
|
|
@@ -27991,6 +28237,9 @@ function RequestRow({
|
|
|
27991
28237
|
const groupIndent = indent + 14;
|
|
27992
28238
|
const { toast, show } = useToast();
|
|
27993
28239
|
const addSecurityTests = useStore$1((s) => s.addSecurityTests);
|
|
28240
|
+
const openWorkspaceSettings = useStore$1((s) => s.openWorkspaceSettings);
|
|
28241
|
+
const [showCloudRequired, setShowCloudRequired] = reactExports.useState(false);
|
|
28242
|
+
const [showShare, setShowShare] = reactExports.useState(false);
|
|
27994
28243
|
function handleRowClick(e) {
|
|
27995
28244
|
if (e.metaKey || e.ctrlKey) {
|
|
27996
28245
|
e.preventDefault();
|
|
@@ -28010,6 +28259,13 @@ function RequestRow({
|
|
|
28010
28259
|
show(e.message, false);
|
|
28011
28260
|
}
|
|
28012
28261
|
}
|
|
28262
|
+
function openShare() {
|
|
28263
|
+
if (!cloudEnabled()) {
|
|
28264
|
+
setShowCloudRequired(true);
|
|
28265
|
+
return;
|
|
28266
|
+
}
|
|
28267
|
+
setShowShare(true);
|
|
28268
|
+
}
|
|
28013
28269
|
const hookMenuItems = ["beforeAll", "before", "after", "afterAll"].map((ht) => ({
|
|
28014
28270
|
type: "item",
|
|
28015
28271
|
label: (hookType === ht ? "✓ " : " ") + t(HOOK_LABELS[ht]),
|
|
@@ -28150,6 +28406,7 @@ function RequestRow({
|
|
|
28150
28406
|
show(n2 > 0 ? t("Added :count OWASP security tests", { count: n2 }) : t("No security tests generated for this request"), n2 > 0);
|
|
28151
28407
|
} },
|
|
28152
28408
|
...cloudEnabled() ? [{ type: "item", label: t("Push as monitor to cloud"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: pushMonitor }] : [],
|
|
28409
|
+
{ type: "item", label: t("Share request (public link)"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: openShare },
|
|
28153
28410
|
{ type: "item", label: disabled ? t("Enable") : t("Disable"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(BanIcon, {}), onClick: onToggleDisabled },
|
|
28154
28411
|
{ type: "separator" },
|
|
28155
28412
|
{ type: "header", label: t("Hook type") },
|
|
@@ -28157,7 +28414,32 @@ function RequestRow({
|
|
|
28157
28414
|
{ type: "separator" },
|
|
28158
28415
|
{ type: "item", label: t("Delete"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TrashIcon, {}), danger: true, onClick: onDelete }
|
|
28159
28416
|
] }) }),
|
|
28160
|
-
toast && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed bottom-4 right-4 z-[100] w-96", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Toast, { toast }) })
|
|
28417
|
+
toast && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed bottom-4 right-4 z-[100] w-96", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Toast, { toast }) }),
|
|
28418
|
+
showCloudRequired && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28419
|
+
CloudRequiredModal,
|
|
28420
|
+
{
|
|
28421
|
+
action: t("share this request"),
|
|
28422
|
+
onConnect: () => {
|
|
28423
|
+
setShowCloudRequired(false);
|
|
28424
|
+
openWorkspaceSettings("cloud");
|
|
28425
|
+
},
|
|
28426
|
+
onClose: () => setShowCloudRequired(false)
|
|
28427
|
+
}
|
|
28428
|
+
),
|
|
28429
|
+
showShare && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
28430
|
+
ShareModal,
|
|
28431
|
+
{
|
|
28432
|
+
title: useStore$1.getState().collections[collectionId]?.data.requests[reqId]?.name ?? "",
|
|
28433
|
+
type: "request",
|
|
28434
|
+
sourceId: reqId,
|
|
28435
|
+
onCreate: () => {
|
|
28436
|
+
const r = useStore$1.getState().collections[collectionId]?.data.requests[reqId];
|
|
28437
|
+
if (!r) throw new Error(t("Request not found"));
|
|
28438
|
+
return shareRequestToCloud(r);
|
|
28439
|
+
},
|
|
28440
|
+
onClose: () => setShowShare(false)
|
|
28441
|
+
}
|
|
28442
|
+
)
|
|
28161
28443
|
]
|
|
28162
28444
|
}
|
|
28163
28445
|
),
|
|
@@ -28818,6 +29100,16 @@ function CollectionNode({
|
|
|
28818
29100
|
const [expandCtrl, setExpandCtrl] = reactExports.useState({ value: true, seq: 0 });
|
|
28819
29101
|
const [dropOver, setDropOver] = reactExports.useState(false);
|
|
28820
29102
|
const dragCtx = reactExports.useContext(DragCtx);
|
|
29103
|
+
const openWorkspaceSettings = useStore$1((s) => s.openWorkspaceSettings);
|
|
29104
|
+
const [showCloudRequired, setShowCloudRequired] = reactExports.useState(false);
|
|
29105
|
+
const [showShare, setShowShare] = reactExports.useState(false);
|
|
29106
|
+
function openShare() {
|
|
29107
|
+
if (!cloudEnabled()) {
|
|
29108
|
+
setShowCloudRequired(true);
|
|
29109
|
+
return;
|
|
29110
|
+
}
|
|
29111
|
+
setShowShare(true);
|
|
29112
|
+
}
|
|
28821
29113
|
function expandAll() {
|
|
28822
29114
|
setExpandCtrl((c) => ({ value: true, seq: c.seq + 1, ids: null }));
|
|
28823
29115
|
}
|
|
@@ -28899,6 +29191,7 @@ function CollectionNode({
|
|
|
28899
29191
|
{ type: "item", label: t("Settings"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(GearIcon, {}), onClick: () => setShowSettings(true) },
|
|
28900
29192
|
{ type: "item", label: t("Sync schemas"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowSchemaSync(true) },
|
|
28901
29193
|
...cloudEnabled() ? [{ type: "item", label: t("Push contract to cloud"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowPushContract(true) }] : [],
|
|
29194
|
+
{ type: "item", label: t("Share collection (public link)"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: openShare },
|
|
28902
29195
|
{ type: "item", label: col.disabled ? t("Enable") : t("Disable"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(BanIcon, {}), onClick: onToggleCollectionDisabled },
|
|
28903
29196
|
{ type: "separator" },
|
|
28904
29197
|
{ type: "item", label: t("Delete collection"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(TrashIcon, {}), danger: true, onClick: onDeleteCollection }
|
|
@@ -28943,7 +29236,28 @@ function CollectionNode({
|
|
|
28943
29236
|
}
|
|
28944
29237
|
),
|
|
28945
29238
|
showSettings && /* @__PURE__ */ jsxRuntimeExports.jsx(CollectionSettingsModal, { collection: col, onClose: () => setShowSettings(false) }),
|
|
28946
|
-
showSchemaSync && /* @__PURE__ */ jsxRuntimeExports.jsx(SchemaSyncModal, { collectionId: col.id, scope: { type: "collection" }, onClose: () => setShowSchemaSync(false) })
|
|
29239
|
+
showSchemaSync && /* @__PURE__ */ jsxRuntimeExports.jsx(SchemaSyncModal, { collectionId: col.id, scope: { type: "collection" }, onClose: () => setShowSchemaSync(false) }),
|
|
29240
|
+
showCloudRequired && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29241
|
+
CloudRequiredModal,
|
|
29242
|
+
{
|
|
29243
|
+
action: t("share this collection"),
|
|
29244
|
+
onConnect: () => {
|
|
29245
|
+
setShowCloudRequired(false);
|
|
29246
|
+
openWorkspaceSettings("cloud");
|
|
29247
|
+
},
|
|
29248
|
+
onClose: () => setShowCloudRequired(false)
|
|
29249
|
+
}
|
|
29250
|
+
),
|
|
29251
|
+
showShare && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29252
|
+
ShareModal,
|
|
29253
|
+
{
|
|
29254
|
+
title: col.name,
|
|
29255
|
+
type: "collection",
|
|
29256
|
+
sourceId: col.id,
|
|
29257
|
+
onCreate: () => shareCollectionToCloud(col),
|
|
29258
|
+
onClose: () => setShowShare(false)
|
|
29259
|
+
}
|
|
29260
|
+
)
|
|
28947
29261
|
] });
|
|
28948
29262
|
}
|
|
28949
29263
|
function FolderRow({
|
|
@@ -28987,6 +29301,16 @@ function FolderRow({
|
|
|
28987
29301
|
}));
|
|
28988
29302
|
const [dropInside, setDropInside] = reactExports.useState(false);
|
|
28989
29303
|
const dragCtx = reactExports.useContext(DragCtx);
|
|
29304
|
+
const openWorkspaceSettings = useStore$1((s) => s.openWorkspaceSettings);
|
|
29305
|
+
const [showCloudRequired, setShowCloudRequired] = reactExports.useState(false);
|
|
29306
|
+
const [showShare, setShowShare] = reactExports.useState(false);
|
|
29307
|
+
function openShare() {
|
|
29308
|
+
if (!cloudEnabled()) {
|
|
29309
|
+
setShowCloudRequired(true);
|
|
29310
|
+
return;
|
|
29311
|
+
}
|
|
29312
|
+
setShowShare(true);
|
|
29313
|
+
}
|
|
28990
29314
|
const tags = folder2.tags ?? [];
|
|
28991
29315
|
const indent = indentPx(depth);
|
|
28992
29316
|
const hasInheritedConfig = folder2.auth && folder2.auth.type !== "none" || folder2.headers && folder2.headers.length > 0;
|
|
@@ -29100,6 +29424,7 @@ function FolderRow({
|
|
|
29100
29424
|
{ type: "item", label: t("Settings"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(GearIcon, {}), onClick: () => setShowSettings(true) },
|
|
29101
29425
|
{ type: "item", label: t("Sync schemas"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowSchemaSync(true) },
|
|
29102
29426
|
...cloudEnabled() ? [{ type: "item", label: t("Push contract to cloud"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(SyncIcon, {}), onClick: () => setShowPushContract(true) }] : [],
|
|
29427
|
+
{ type: "item", label: t("Share folder (public link)"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(CopyIcon, {}), onClick: openShare },
|
|
29103
29428
|
{ type: "item", label: folder2.disabled ? t("Enable") : t("Disable"), icon: /* @__PURE__ */ jsxRuntimeExports.jsx(BanIcon, {}), onClick: onToggleDisabled },
|
|
29104
29429
|
{ type: "separator" },
|
|
29105
29430
|
{ type: "header", label: t("Run folder as hook") },
|
|
@@ -29134,6 +29459,27 @@ function FolderRow({
|
|
|
29134
29459
|
scope: { type: "folder", folderId: folder2.id },
|
|
29135
29460
|
onClose: () => setShowSchemaSync(false)
|
|
29136
29461
|
}
|
|
29462
|
+
),
|
|
29463
|
+
showCloudRequired && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29464
|
+
CloudRequiredModal,
|
|
29465
|
+
{
|
|
29466
|
+
action: t("share this folder"),
|
|
29467
|
+
onConnect: () => {
|
|
29468
|
+
setShowCloudRequired(false);
|
|
29469
|
+
openWorkspaceSettings("cloud");
|
|
29470
|
+
},
|
|
29471
|
+
onClose: () => setShowCloudRequired(false)
|
|
29472
|
+
}
|
|
29473
|
+
),
|
|
29474
|
+
showShare && folderCollection && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
29475
|
+
ShareModal,
|
|
29476
|
+
{
|
|
29477
|
+
title: folder2.name,
|
|
29478
|
+
type: "folder",
|
|
29479
|
+
sourceId: folder2.id,
|
|
29480
|
+
onCreate: () => shareFolderToCloud(folderCollection, folder2),
|
|
29481
|
+
onClose: () => setShowShare(false)
|
|
29482
|
+
}
|
|
29137
29483
|
)
|
|
29138
29484
|
] });
|
|
29139
29485
|
}
|
|
@@ -29587,8 +29933,8 @@ function jsonWithComments() {
|
|
|
29587
29933
|
function xmlWithComments() {
|
|
29588
29934
|
return [xml(), commentKeymap];
|
|
29589
29935
|
}
|
|
29590
|
-
const GraphQLEditor = reactExports.lazy(() => __vitePreload(() => import("./GraphQLEditor-
|
|
29591
|
-
const SoapEditor = reactExports.lazy(() => __vitePreload(() => import("./SoapEditor-
|
|
29936
|
+
const GraphQLEditor = reactExports.lazy(() => __vitePreload(() => import("./GraphQLEditor-RRDuQogA.js"), true ? __vite__mapDeps([0,1,2]) : void 0, import.meta.url).then((m) => ({ default: m.GraphQLEditor })));
|
|
29937
|
+
const SoapEditor = reactExports.lazy(() => __vitePreload(() => import("./SoapEditor-BncNQmjP.js"), true ? __vite__mapDeps([3,1,2]) : void 0, import.meta.url).then((m) => ({ default: m.SoapEditor })));
|
|
29592
29938
|
function BodyTab({ request: request2, onChange }) {
|
|
29593
29939
|
const t = useT();
|
|
29594
29940
|
const editorFallback = /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 text-xs text-surface-500", children: t("Loading editor…") });
|
|
@@ -29686,7 +30032,7 @@ function BodyTab({ request: request2, onChange }) {
|
|
|
29686
30032
|
mode === "soap" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: editorFallback, children: /* @__PURE__ */ jsxRuntimeExports.jsx(SoapEditor, { request: request2, onChange }) }) })
|
|
29687
30033
|
] });
|
|
29688
30034
|
}
|
|
29689
|
-
const { electron: electron$
|
|
30035
|
+
const { electron: electron$E } = window;
|
|
29690
30036
|
function AuthTab({ request: request2, onChange }) {
|
|
29691
30037
|
const auth = request2.auth;
|
|
29692
30038
|
const [secretValue, setSecretValue] = reactExports.useState("");
|
|
@@ -29696,7 +30042,7 @@ function AuthTab({ request: request2, onChange }) {
|
|
|
29696
30042
|
}
|
|
29697
30043
|
async function saveSecret(ref) {
|
|
29698
30044
|
if (!secretValue || !ref) return;
|
|
29699
|
-
await electron$
|
|
30045
|
+
await electron$E.setSecret(ref, secretValue);
|
|
29700
30046
|
setSaved(true);
|
|
29701
30047
|
setSecretValue("");
|
|
29702
30048
|
setTimeout(() => setSaved(false), 2e3);
|
|
@@ -30056,7 +30402,7 @@ function validateBodyAgainstSchema(schema, body) {
|
|
|
30056
30402
|
return { status: "error", message: e instanceof Error ? e.message : String(e) };
|
|
30057
30403
|
}
|
|
30058
30404
|
}
|
|
30059
|
-
const { electron: electron$
|
|
30405
|
+
const { electron: electron$D } = window;
|
|
30060
30406
|
function SchemaTab({ request: request2, onChange }) {
|
|
30061
30407
|
const t = useT();
|
|
30062
30408
|
const activeTab = useStore$1((s) => s.tabs.find((tab) => tab.id === s.activeTabId));
|
|
@@ -30080,7 +30426,7 @@ function SchemaTab({ request: request2, onChange }) {
|
|
|
30080
30426
|
if (!lastResponse?.body) return;
|
|
30081
30427
|
setInferring(true);
|
|
30082
30428
|
try {
|
|
30083
|
-
const schema = await electron$
|
|
30429
|
+
const schema = await electron$D.inferContractSchema(lastResponse.body);
|
|
30084
30430
|
if (schema) setSchema(schema);
|
|
30085
30431
|
} finally {
|
|
30086
30432
|
setInferring(false);
|
|
@@ -39510,7 +39856,7 @@ function DocsEditor({ value: value2, onChange, placeholder, onGenerate, aiAvaila
|
|
|
39510
39856
|
}
|
|
39511
39857
|
const AI_OPENAI_TOKEN_REF = "ai:openai:token";
|
|
39512
39858
|
const DEFAULT_AI_MODEL = "gpt-4o-mini";
|
|
39513
|
-
const { electron: electron$
|
|
39859
|
+
const { electron: electron$C } = window;
|
|
39514
39860
|
const CFG_KEY = STORAGE_KEYS.ai;
|
|
39515
39861
|
function getAiConfig() {
|
|
39516
39862
|
try {
|
|
@@ -39532,7 +39878,7 @@ function invalidateAiAvailable() {
|
|
|
39532
39878
|
async function checkAvailable() {
|
|
39533
39879
|
if (availableCache != null) return availableCache;
|
|
39534
39880
|
try {
|
|
39535
|
-
availableCache = (await electron$
|
|
39881
|
+
availableCache = (await electron$C.hasSecret(AI_OPENAI_TOKEN_REF)).has;
|
|
39536
39882
|
} catch {
|
|
39537
39883
|
availableCache = false;
|
|
39538
39884
|
}
|
|
@@ -39552,7 +39898,7 @@ function useAiAvailable() {
|
|
|
39552
39898
|
return available;
|
|
39553
39899
|
}
|
|
39554
39900
|
async function generateDocs(input) {
|
|
39555
|
-
return electron$
|
|
39901
|
+
return electron$C.generateAiDocs({ ...input, model: getAiConfig().model });
|
|
39556
39902
|
}
|
|
39557
39903
|
function kvLines(label, rows) {
|
|
39558
39904
|
const on = (rows ?? []).filter((r) => r.enabled !== false && r.key);
|
|
@@ -40080,7 +40426,7 @@ function RealtimeTestSection({
|
|
|
40080
40426
|
] })
|
|
40081
40427
|
] });
|
|
40082
40428
|
}
|
|
40083
|
-
const { electron: electron$
|
|
40429
|
+
const { electron: electron$B } = window;
|
|
40084
40430
|
function formatTime$4(ts) {
|
|
40085
40431
|
const d = new Date(ts);
|
|
40086
40432
|
const hh = String(d.getHours()).padStart(2, "0");
|
|
@@ -40110,7 +40456,7 @@ function WebSocketPanel({ request: request2, onChange }) {
|
|
|
40110
40456
|
const url = interp(request2.url).trim();
|
|
40111
40457
|
const headers = {};
|
|
40112
40458
|
for (const h of request2.headers) if (h.enabled && h.key) headers[interp(h.key)] = interp(h.value);
|
|
40113
|
-
return electron$
|
|
40459
|
+
return electron$B.wsTest({
|
|
40114
40460
|
url,
|
|
40115
40461
|
headers,
|
|
40116
40462
|
sendMessage: cfg.sendMessage ? interp(cfg.sendMessage) : void 0,
|
|
@@ -40120,14 +40466,14 @@ function WebSocketPanel({ request: request2, onChange }) {
|
|
|
40120
40466
|
});
|
|
40121
40467
|
});
|
|
40122
40468
|
reactExports.useEffect(() => {
|
|
40123
|
-
electron$
|
|
40469
|
+
electron$B.onWsMessage(({ requestId, message }) => {
|
|
40124
40470
|
addWsMessage(requestId, message);
|
|
40125
40471
|
});
|
|
40126
|
-
electron$
|
|
40472
|
+
electron$B.onWsStatus(({ requestId, status, error: error2 }) => {
|
|
40127
40473
|
setWsStatus(requestId, status, error2);
|
|
40128
40474
|
});
|
|
40129
40475
|
return () => {
|
|
40130
|
-
electron$
|
|
40476
|
+
electron$B.offWsEvents();
|
|
40131
40477
|
};
|
|
40132
40478
|
}, [addWsMessage, setWsStatus]);
|
|
40133
40479
|
reactExports.useEffect(() => {
|
|
@@ -40140,19 +40486,19 @@ function WebSocketPanel({ request: request2, onChange }) {
|
|
|
40140
40486
|
if (h.enabled && h.key) headers[h.key] = h.value;
|
|
40141
40487
|
}
|
|
40142
40488
|
try {
|
|
40143
|
-
await electron$
|
|
40489
|
+
await electron$B.wsConnect(request2.id, request2.url, headers);
|
|
40144
40490
|
} catch (err) {
|
|
40145
40491
|
setWsStatus(request2.id, "error", err instanceof Error ? err.message : String(err));
|
|
40146
40492
|
}
|
|
40147
40493
|
}
|
|
40148
40494
|
async function disconnect() {
|
|
40149
|
-
await electron$
|
|
40495
|
+
await electron$B.wsDisconnect(request2.id);
|
|
40150
40496
|
}
|
|
40151
40497
|
async function sendMessage() {
|
|
40152
40498
|
const text = sendText.trim();
|
|
40153
40499
|
if (!text || !isConnected) return;
|
|
40154
40500
|
try {
|
|
40155
|
-
await electron$
|
|
40501
|
+
await electron$B.wsSend(request2.id, text);
|
|
40156
40502
|
const msg = {
|
|
40157
40503
|
id: crypto.randomUUID(),
|
|
40158
40504
|
direction: "sent",
|
|
@@ -40304,7 +40650,7 @@ function WebSocketPanel({ request: request2, onChange }) {
|
|
|
40304
40650
|
] })
|
|
40305
40651
|
] });
|
|
40306
40652
|
}
|
|
40307
|
-
const { electron: electron$
|
|
40653
|
+
const { electron: electron$A } = window;
|
|
40308
40654
|
function formatTime$3(ts) {
|
|
40309
40655
|
const d = new Date(ts);
|
|
40310
40656
|
const p = (n2, w = 2) => String(n2).padStart(w, "0");
|
|
@@ -40338,7 +40684,7 @@ function SocketIoPanel({ request: request2, onChange }) {
|
|
|
40338
40684
|
const url = interp(request2.url).trim();
|
|
40339
40685
|
const headers = {};
|
|
40340
40686
|
for (const h of request2.headers) if (h.enabled && h.key) headers[interp(h.key)] = interp(h.value);
|
|
40341
|
-
return electron$
|
|
40687
|
+
return electron$A.socketIoTest({
|
|
40342
40688
|
url,
|
|
40343
40689
|
namespace: namespace2,
|
|
40344
40690
|
auth: auth ? interp(auth) : void 0,
|
|
@@ -40357,19 +40703,19 @@ function SocketIoPanel({ request: request2, onChange }) {
|
|
|
40357
40703
|
if (h.enabled && h.key) headers[h.key] = h.value;
|
|
40358
40704
|
}
|
|
40359
40705
|
try {
|
|
40360
|
-
await electron$
|
|
40706
|
+
await electron$A.socketIoConnect(request2.id, { url: request2.url, namespace: namespace2, auth, headers });
|
|
40361
40707
|
} catch (err) {
|
|
40362
40708
|
setStatus(request2.id, "error", err instanceof Error ? err.message : String(err));
|
|
40363
40709
|
}
|
|
40364
40710
|
}
|
|
40365
40711
|
async function disconnect() {
|
|
40366
|
-
await electron$
|
|
40712
|
+
await electron$A.socketIoDisconnect(request2.id);
|
|
40367
40713
|
}
|
|
40368
40714
|
async function emit() {
|
|
40369
40715
|
const event = eventName2.trim();
|
|
40370
40716
|
if (!event || !isConnected) return;
|
|
40371
40717
|
try {
|
|
40372
|
-
await electron$
|
|
40718
|
+
await electron$A.socketIoEmit(request2.id, { event, args: argsText, withAck });
|
|
40373
40719
|
const msg = {
|
|
40374
40720
|
id: crypto.randomUUID(),
|
|
40375
40721
|
direction: "sent",
|
|
@@ -40583,7 +40929,7 @@ function SocketIoPanel({ request: request2, onChange }) {
|
|
|
40583
40929
|
] })
|
|
40584
40930
|
] });
|
|
40585
40931
|
}
|
|
40586
|
-
const { electron: electron$
|
|
40932
|
+
const { electron: electron$z } = window;
|
|
40587
40933
|
function formatTime$2(ts) {
|
|
40588
40934
|
const d = new Date(ts);
|
|
40589
40935
|
const p = (n2, w = 2) => String(n2).padStart(w, "0");
|
|
@@ -40623,7 +40969,7 @@ function MqttPanel({ request: request2, onChange }) {
|
|
|
40623
40969
|
return;
|
|
40624
40970
|
}
|
|
40625
40971
|
try {
|
|
40626
|
-
await electron$
|
|
40972
|
+
await electron$z.mqttConnect(request2.id, {
|
|
40627
40973
|
url,
|
|
40628
40974
|
clientId: cfg.clientId ? interp(cfg.clientId) : void 0,
|
|
40629
40975
|
username: cfg.username ? interp(cfg.username) : void 0,
|
|
@@ -40637,13 +40983,13 @@ function MqttPanel({ request: request2, onChange }) {
|
|
|
40637
40983
|
}
|
|
40638
40984
|
}
|
|
40639
40985
|
async function disconnect() {
|
|
40640
|
-
await electron$
|
|
40986
|
+
await electron$z.mqttDisconnect(request2.id);
|
|
40641
40987
|
}
|
|
40642
40988
|
async function subscribe() {
|
|
40643
40989
|
const topic = interp(cfg.subscribeTopic ?? "").trim();
|
|
40644
40990
|
if (!topic || !isConnected) return;
|
|
40645
40991
|
try {
|
|
40646
|
-
await electron$
|
|
40992
|
+
await electron$z.mqttSubscribe(request2.id, { topic, qos });
|
|
40647
40993
|
} catch (err) {
|
|
40648
40994
|
setStatus(request2.id, "error", err instanceof Error ? err.message : String(err));
|
|
40649
40995
|
}
|
|
@@ -40651,7 +40997,7 @@ function MqttPanel({ request: request2, onChange }) {
|
|
|
40651
40997
|
async function unsubscribe() {
|
|
40652
40998
|
const topic = interp(cfg.subscribeTopic ?? "").trim();
|
|
40653
40999
|
if (!topic || !isConnected) return;
|
|
40654
|
-
await electron$
|
|
41000
|
+
await electron$z.mqttUnsubscribe(request2.id, { topic });
|
|
40655
41001
|
}
|
|
40656
41002
|
async function publish() {
|
|
40657
41003
|
const topic = interp(cfg.publishTopic ?? "").trim();
|
|
@@ -40663,7 +41009,7 @@ function MqttPanel({ request: request2, onChange }) {
|
|
|
40663
41009
|
setPublishError("");
|
|
40664
41010
|
const body = interp(payload);
|
|
40665
41011
|
try {
|
|
40666
|
-
await electron$
|
|
41012
|
+
await electron$z.mqttPublish(request2.id, { topic, payload: body, qos, retain: Boolean(cfg.retain) });
|
|
40667
41013
|
addMessage(request2.id, {
|
|
40668
41014
|
id: crypto.randomUUID(),
|
|
40669
41015
|
direction: "sent",
|
|
@@ -40687,7 +41033,7 @@ function MqttPanel({ request: request2, onChange }) {
|
|
|
40687
41033
|
setTestRemaining(Math.ceil(collectMs / 1e3));
|
|
40688
41034
|
const countdown = setInterval(() => setTestRemaining((r) => r && r > 1 ? r - 1 : 0), 1e3);
|
|
40689
41035
|
try {
|
|
40690
|
-
const res = await electron$
|
|
41036
|
+
const res = await electron$z.mqttTest({
|
|
40691
41037
|
url,
|
|
40692
41038
|
// The test opens its own connection; never reuse the panel's Client ID,
|
|
40693
41039
|
// or the broker would kick whichever connected first (a clientId clash).
|
|
@@ -41036,7 +41382,7 @@ function MqttPanel({ request: request2, onChange }) {
|
|
|
41036
41382
|
] })
|
|
41037
41383
|
] });
|
|
41038
41384
|
}
|
|
41039
|
-
const { electron: electron$
|
|
41385
|
+
const { electron: electron$y } = window;
|
|
41040
41386
|
function formatTime$1(ts) {
|
|
41041
41387
|
const d = new Date(ts);
|
|
41042
41388
|
const p = (n2, w = 2) => String(n2).padStart(w, "0");
|
|
@@ -41072,13 +41418,13 @@ function GrpcPanel({ request: request2, onChange }) {
|
|
|
41072
41418
|
onChange({ body: { ...request2.body, mode: "grpc", grpc: { ...grpc, ...changes } } });
|
|
41073
41419
|
}
|
|
41074
41420
|
reactExports.useEffect(() => {
|
|
41075
|
-
electron$
|
|
41421
|
+
electron$y.onGrpcMessage(({ requestId, message }) => {
|
|
41076
41422
|
addGrpcMessage(requestId, message);
|
|
41077
41423
|
});
|
|
41078
|
-
electron$
|
|
41424
|
+
electron$y.onGrpcStatus(({ requestId, status, code, codeName, error: error2 }) => {
|
|
41079
41425
|
setGrpcStatus(requestId, status, { code, codeName, error: error2 });
|
|
41080
41426
|
});
|
|
41081
|
-
return () => electron$
|
|
41427
|
+
return () => electron$y.offGrpcEvents();
|
|
41082
41428
|
}, [addGrpcMessage, setGrpcStatus]);
|
|
41083
41429
|
reactExports.useEffect(() => {
|
|
41084
41430
|
logEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
@@ -41091,7 +41437,7 @@ function GrpcPanel({ request: request2, onChange }) {
|
|
|
41091
41437
|
if (!grpc.protoSource?.trim() && !grpc.protoPath?.trim()) return;
|
|
41092
41438
|
setLoadingProto(true);
|
|
41093
41439
|
try {
|
|
41094
|
-
const result = await electron$
|
|
41440
|
+
const result = await electron$y.grpcLoadProto({ protoSource: grpc.protoSource, protoPath: grpc.protoPath });
|
|
41095
41441
|
const services = result.services;
|
|
41096
41442
|
setGrpcServices(request2.id, services);
|
|
41097
41443
|
if (services.length && !services.some((s) => s.name === grpc.serviceName)) {
|
|
@@ -41110,7 +41456,7 @@ function GrpcPanel({ request: request2, onChange }) {
|
|
|
41110
41456
|
const metadata = {};
|
|
41111
41457
|
for (const m of grpc.metadata ?? []) if (m.enabled && m.key) metadata[m.key] = m.value;
|
|
41112
41458
|
try {
|
|
41113
|
-
await electron$
|
|
41459
|
+
await electron$y.grpcInvoke(request2.id, {
|
|
41114
41460
|
target: request2.url,
|
|
41115
41461
|
serviceName: grpc.serviceName,
|
|
41116
41462
|
methodName: grpc.methodName,
|
|
@@ -41125,7 +41471,7 @@ function GrpcPanel({ request: request2, onChange }) {
|
|
|
41125
41471
|
}
|
|
41126
41472
|
}
|
|
41127
41473
|
function cancel() {
|
|
41128
|
-
electron$
|
|
41474
|
+
electron$y.grpcCancel(request2.id);
|
|
41129
41475
|
}
|
|
41130
41476
|
const statusColors = {
|
|
41131
41477
|
running: "bg-amber-400",
|
|
@@ -41249,7 +41595,7 @@ function GrpcPanel({ request: request2, onChange }) {
|
|
|
41249
41595
|
] })
|
|
41250
41596
|
] });
|
|
41251
41597
|
}
|
|
41252
|
-
const { electron: electron$
|
|
41598
|
+
const { electron: electron$x } = window;
|
|
41253
41599
|
function isSubscriptionQuery(query) {
|
|
41254
41600
|
return /(^|\n)\s*subscription\b/i.test(query ?? "");
|
|
41255
41601
|
}
|
|
@@ -41298,7 +41644,7 @@ function GraphQlSubscription({ request: request2, gql, onPatch }) {
|
|
|
41298
41644
|
const headers = {};
|
|
41299
41645
|
for (const h of request2.headers) if (h.enabled && h.key) headers[interp(h.key)] = interp(h.value);
|
|
41300
41646
|
try {
|
|
41301
|
-
await electron$
|
|
41647
|
+
await electron$x.graphqlWsSubscribe(request2.id, {
|
|
41302
41648
|
url,
|
|
41303
41649
|
headers,
|
|
41304
41650
|
query: gql.query,
|
|
@@ -41315,7 +41661,7 @@ function GraphQlSubscription({ request: request2, gql, onPatch }) {
|
|
|
41315
41661
|
const url = deriveWsUrl(interp(rawUrl));
|
|
41316
41662
|
const headers = {};
|
|
41317
41663
|
for (const h of request2.headers) if (h.enabled && h.key) headers[interp(h.key)] = interp(h.value);
|
|
41318
|
-
return electron$
|
|
41664
|
+
return electron$x.graphqlWsTest({
|
|
41319
41665
|
url,
|
|
41320
41666
|
headers,
|
|
41321
41667
|
query: gql.query,
|
|
@@ -41350,7 +41696,7 @@ function GraphQlSubscription({ request: request2, gql, onPatch }) {
|
|
|
41350
41696
|
className: "flex-1 bg-surface-800 border border-surface-700 rounded px-2 py-1 text-xs font-mono focus:outline-none focus:border-blue-500 placeholder-surface-600 disabled:opacity-50"
|
|
41351
41697
|
}
|
|
41352
41698
|
),
|
|
41353
|
-
isActive ? /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => electron$
|
|
41699
|
+
isActive ? /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => electron$x.graphqlWsStop(request2.id), className: "px-3 py-1 bg-red-700 hover:bg-red-600 rounded text-xs font-medium transition-colors whitespace-nowrap", children: conn.status === "connecting" ? t("Connecting…") : t("Stop") }) : /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: subscribe, className: "px-3 py-1 bg-fuchsia-700 hover:bg-fuchsia-600 rounded text-xs font-medium transition-colors whitespace-nowrap", children: t("Subscribe") })
|
|
41354
41700
|
] }),
|
|
41355
41701
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-shrink-0", children: [
|
|
41356
41702
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: () => setShowParams((v) => !v), className: "text-[10px] text-surface-600 hover:text-surface-300 transition-colors", children: [
|
|
@@ -41618,7 +41964,7 @@ function FuzzResultsPanel({ report, onClear }) {
|
|
|
41618
41964
|
] }) })
|
|
41619
41965
|
] });
|
|
41620
41966
|
}
|
|
41621
|
-
const { electron: electron$
|
|
41967
|
+
const { electron: electron$w } = window;
|
|
41622
41968
|
const WRITE_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
41623
41969
|
function FuzzModal({ request: request2, onClose }) {
|
|
41624
41970
|
const t = useT();
|
|
@@ -41646,7 +41992,7 @@ function FuzzModal({ request: request2, onClose }) {
|
|
|
41646
41992
|
const env2 = resolveEnvironmentById(environments, activeEnvironmentId);
|
|
41647
41993
|
const envVars = env2 ? Object.fromEntries(env2.variables.filter((v) => v.enabled).map((v) => [v.key, v.value])) : {};
|
|
41648
41994
|
const collectionVars = activeCollectionId ? collections[activeCollectionId]?.data.collectionVariables ?? {} : {};
|
|
41649
|
-
const result = await electron$
|
|
41995
|
+
const result = await electron$w.fuzzContracts({
|
|
41650
41996
|
requests: [request2],
|
|
41651
41997
|
envVars,
|
|
41652
41998
|
collectionVars,
|
|
@@ -41863,7 +42209,7 @@ function resolveAskValues(asks, answers) {
|
|
|
41863
42209
|
for (const a of asks) out[a.key] = answers[a.message] ?? "";
|
|
41864
42210
|
return out;
|
|
41865
42211
|
}
|
|
41866
|
-
const { electron: electron$
|
|
42212
|
+
const { electron: electron$v } = window;
|
|
41867
42213
|
const METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "QUERY"];
|
|
41868
42214
|
const METHOD_COLORS = {
|
|
41869
42215
|
GET: "text-emerald-400",
|
|
@@ -42009,7 +42355,7 @@ function RequestBuilder({ request: request2 }) {
|
|
|
42009
42355
|
const headers = {};
|
|
42010
42356
|
for (const h of request2.headers) if (h.enabled && h.key) headers[interp(h.key)] = interp(h.value);
|
|
42011
42357
|
try {
|
|
42012
|
-
await electron$
|
|
42358
|
+
await electron$v.graphqlWsSubscribe(request2.id, {
|
|
42013
42359
|
url,
|
|
42014
42360
|
headers,
|
|
42015
42361
|
query: gql.query,
|
|
@@ -42070,7 +42416,7 @@ function RequestBuilder({ request: request2 }) {
|
|
|
42070
42416
|
const start2 = Date.now();
|
|
42071
42417
|
try {
|
|
42072
42418
|
const hookEnv = withEnvOverrides(activeEnv, liveEnvOverrides);
|
|
42073
|
-
const r = await electron$
|
|
42419
|
+
const r = await electron$v.sendRequest({
|
|
42074
42420
|
...basePayload,
|
|
42075
42421
|
environment: hookEnv,
|
|
42076
42422
|
request: hook,
|
|
@@ -42122,7 +42468,7 @@ function RequestBuilder({ request: request2 }) {
|
|
|
42122
42468
|
startLiveStream(activeTabId, streamId);
|
|
42123
42469
|
let result;
|
|
42124
42470
|
try {
|
|
42125
|
-
result = await electron$
|
|
42471
|
+
result = await electron$v.sendRequest({
|
|
42126
42472
|
...basePayload,
|
|
42127
42473
|
environment: freshEnv,
|
|
42128
42474
|
request: mergedRequest,
|
|
@@ -42159,7 +42505,7 @@ function RequestBuilder({ request: request2 }) {
|
|
|
42159
42505
|
const start2 = Date.now();
|
|
42160
42506
|
try {
|
|
42161
42507
|
const hookEnv = withEnvOverrides(activeEnv, liveEnvOverrides);
|
|
42162
|
-
const r = await electron$
|
|
42508
|
+
const r = await electron$v.sendRequest({
|
|
42163
42509
|
...basePayload,
|
|
42164
42510
|
environment: hookEnv,
|
|
42165
42511
|
request: hook,
|
|
@@ -43342,7 +43688,7 @@ function Cell({ value: value2, onDrill }) {
|
|
|
43342
43688
|
const text = String(value2);
|
|
43343
43689
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-block max-w-[26rem] truncate align-bottom text-surface-300", title: text.length > 40 ? text : void 0, children: text });
|
|
43344
43690
|
}
|
|
43345
|
-
const { electron: electron$
|
|
43691
|
+
const { electron: electron$u } = window;
|
|
43346
43692
|
const RENDER_TAIL = 500;
|
|
43347
43693
|
const CLOSE_LABEL = {
|
|
43348
43694
|
complete: "closed",
|
|
@@ -43384,7 +43730,7 @@ function StreamView({ events, streaming: streaming2, streamId, streamClose, firs
|
|
|
43384
43730
|
if (!streamId) return;
|
|
43385
43731
|
setStopping(true);
|
|
43386
43732
|
try {
|
|
43387
|
-
await electron$
|
|
43733
|
+
await electron$u.stopStream(streamId);
|
|
43388
43734
|
} catch {
|
|
43389
43735
|
}
|
|
43390
43736
|
}
|
|
@@ -43527,7 +43873,7 @@ function HookResultsPanel({ results }) {
|
|
|
43527
43873
|
}) })
|
|
43528
43874
|
] });
|
|
43529
43875
|
}
|
|
43530
|
-
const { electron: electron$
|
|
43876
|
+
const { electron: electron$t } = window;
|
|
43531
43877
|
function extractPath(url) {
|
|
43532
43878
|
try {
|
|
43533
43879
|
return new URL(url).pathname || "/";
|
|
@@ -43582,14 +43928,14 @@ function SaveAsMockModal({ onClose }) {
|
|
|
43582
43928
|
const entry = state.mocks[serverId];
|
|
43583
43929
|
const updated = { ...entry.data, name: newServerName, port: Number(newServerPort), routes: [route] };
|
|
43584
43930
|
updateMock(serverId, updated);
|
|
43585
|
-
await electron$
|
|
43931
|
+
await electron$t.saveMock(entry.relPath, updated);
|
|
43586
43932
|
const ws = useStore$1.getState().workspace;
|
|
43587
|
-
if (ws) await electron$
|
|
43933
|
+
if (ws) await electron$t.saveWorkspace(ws);
|
|
43588
43934
|
} else {
|
|
43589
43935
|
const entry = useStore$1.getState().mocks[serverId];
|
|
43590
43936
|
const updated = { ...entry.data, routes: [...entry.data.routes, route] };
|
|
43591
43937
|
updateMock(serverId, updated);
|
|
43592
|
-
await electron$
|
|
43938
|
+
await electron$t.saveMock(entry.relPath, updated);
|
|
43593
43939
|
}
|
|
43594
43940
|
onClose();
|
|
43595
43941
|
} finally {
|
|
@@ -44107,7 +44453,7 @@ function validateHttpSemantics(res, opts = {}) {
|
|
|
44107
44453
|
const order = { error: 0, warning: 1, hint: 2 };
|
|
44108
44454
|
return f.sort((a, b) => order[a.severity] - order[b.severity]);
|
|
44109
44455
|
}
|
|
44110
|
-
const { electron: electron$
|
|
44456
|
+
const { electron: electron$s } = window;
|
|
44111
44457
|
function xmlWellFormed(body) {
|
|
44112
44458
|
try {
|
|
44113
44459
|
const doc = new DOMParser().parseFromString(body, "application/xml");
|
|
@@ -44337,7 +44683,7 @@ function ResponseViewer() {
|
|
|
44337
44683
|
const schemaCheck = currentRequest?.schema?.trim() && response && !response.error ? validateBodyAgainstSchema(currentRequest.schema, response.body) : null;
|
|
44338
44684
|
async function saveAsSchema() {
|
|
44339
44685
|
if (!response || !requestId || !activeTabId) return;
|
|
44340
|
-
const schema = response.body ? await electron$
|
|
44686
|
+
const schema = response.body ? await electron$s.inferContractSchema(response.body) : null;
|
|
44341
44687
|
if (!schema) return;
|
|
44342
44688
|
updateRequest(requestId, { schema });
|
|
44343
44689
|
setTabRequestTab(activeTabId, "schema");
|
|
@@ -44925,7 +45271,7 @@ function listFolders(root2, depth = 0, out = []) {
|
|
|
44925
45271
|
}
|
|
44926
45272
|
return out;
|
|
44927
45273
|
}
|
|
44928
|
-
const { electron: electron$
|
|
45274
|
+
const { electron: electron$r } = window;
|
|
44929
45275
|
function fmtMs(ms) {
|
|
44930
45276
|
if (ms < 1) return "<1 ms";
|
|
44931
45277
|
if (ms < 1e3) return `${Math.round(ms)} ms`;
|
|
@@ -45116,11 +45462,11 @@ function PerformancePanel() {
|
|
|
45116
45462
|
setError("");
|
|
45117
45463
|
}, [activeId]);
|
|
45118
45464
|
reactExports.useEffect(() => {
|
|
45119
|
-
electron$
|
|
45465
|
+
electron$r.onPerfProgress((p) => {
|
|
45120
45466
|
setProgress(p);
|
|
45121
45467
|
setSamples((s) => [...s, p].slice(-240));
|
|
45122
45468
|
});
|
|
45123
|
-
return () => electron$
|
|
45469
|
+
return () => electron$r.offPerfEvents();
|
|
45124
45470
|
}, []);
|
|
45125
45471
|
const requestOptions = reactExports.useMemo(() => {
|
|
45126
45472
|
const out = [];
|
|
@@ -45167,7 +45513,7 @@ function PerformancePanel() {
|
|
|
45167
45513
|
if (saveTimer2.current) clearTimeout(saveTimer2.current);
|
|
45168
45514
|
saveTimer2.current = setTimeout(() => {
|
|
45169
45515
|
const ws = useStore$1.getState().workspace;
|
|
45170
|
-
if (ws) void electron$
|
|
45516
|
+
if (ws) void electron$r.saveWorkspace(ws);
|
|
45171
45517
|
}, 500);
|
|
45172
45518
|
}
|
|
45173
45519
|
async function run() {
|
|
@@ -45192,7 +45538,7 @@ function PerformancePanel() {
|
|
|
45192
45538
|
collections: Object.values(collections).map((c) => c.data),
|
|
45193
45539
|
...common
|
|
45194
45540
|
};
|
|
45195
|
-
setResult(await electron$
|
|
45541
|
+
setResult(await electron$r.perfRun(payload));
|
|
45196
45542
|
} catch (err) {
|
|
45197
45543
|
setError(err instanceof Error ? err.message : String(err));
|
|
45198
45544
|
} finally {
|
|
@@ -45201,14 +45547,14 @@ function PerformancePanel() {
|
|
|
45201
45547
|
}
|
|
45202
45548
|
}
|
|
45203
45549
|
async function stop() {
|
|
45204
|
-
await electron$
|
|
45550
|
+
await electron$r.perfStop();
|
|
45205
45551
|
}
|
|
45206
45552
|
async function exportReport() {
|
|
45207
45553
|
if (!result || !plan) return;
|
|
45208
45554
|
setExporting(true);
|
|
45209
45555
|
try {
|
|
45210
45556
|
const target = plan.target.kind === "request" ? selectedRequest?.name ?? "request" : selectedFlow?.name ?? "flow";
|
|
45211
|
-
await electron$
|
|
45557
|
+
await electron$r.perfExportHtml(result, { planName: plan.name, target });
|
|
45212
45558
|
} catch (err) {
|
|
45213
45559
|
setError(err instanceof Error ? err.message : String(err));
|
|
45214
45560
|
} finally {
|
|
@@ -45643,7 +45989,7 @@ function PerformancePanel() {
|
|
|
45643
45989
|
!result && !running && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0 flex items-center justify-center text-sm text-surface-500", children: t("Set the load and run this plan.") })
|
|
45644
45990
|
] });
|
|
45645
45991
|
}
|
|
45646
|
-
const { electron: electron$
|
|
45992
|
+
const { electron: electron$q } = window;
|
|
45647
45993
|
function makePlan(name) {
|
|
45648
45994
|
return {
|
|
45649
45995
|
id: crypto.randomUUID(),
|
|
@@ -45680,7 +46026,7 @@ function PerfPlansPanel() {
|
|
|
45680
46026
|
const updated = { ...workspace, perfPlans: next };
|
|
45681
46027
|
setWorkspace(updated, workspacePath ?? "");
|
|
45682
46028
|
try {
|
|
45683
|
-
await electron$
|
|
46029
|
+
await electron$q.saveWorkspace(updated);
|
|
45684
46030
|
} catch {
|
|
45685
46031
|
}
|
|
45686
46032
|
}
|
|
@@ -45824,7 +46170,7 @@ class ErrorBoundary extends React.Component {
|
|
|
45824
46170
|
] });
|
|
45825
46171
|
}
|
|
45826
46172
|
}
|
|
45827
|
-
const { electron: electron$
|
|
46173
|
+
const { electron: electron$p } = window;
|
|
45828
46174
|
const TARGETS = [
|
|
45829
46175
|
{ id: "robot_framework", label: "Robot Framework", description: "Python RequestsLibrary keywords + test suite" },
|
|
45830
46176
|
{ id: "playwright_ts", label: "Playwright TS", description: "TypeScript page-object API classes + spec files" },
|
|
@@ -45866,7 +46212,7 @@ function GeneratorPanel() {
|
|
|
45866
46212
|
try {
|
|
45867
46213
|
const col = collections[selectedCollectionId]?.data;
|
|
45868
46214
|
const env2 = resolveEnvironmentById(environments, activeEnvironmentId);
|
|
45869
|
-
const generated = await electron$
|
|
46215
|
+
const generated = await electron$p.generateCode({ collection: col, environment: env2, target });
|
|
45870
46216
|
setFiles(generated);
|
|
45871
46217
|
setSelectedFile(generated[0]?.path ?? null);
|
|
45872
46218
|
} catch (e) {
|
|
@@ -45878,7 +46224,7 @@ function GeneratorPanel() {
|
|
|
45878
46224
|
async function saveZip() {
|
|
45879
46225
|
if (files.length === 0) return;
|
|
45880
46226
|
const col = collections[selectedCollectionId]?.data;
|
|
45881
|
-
await electron$
|
|
46227
|
+
await electron$p.saveGeneratedFilesAsZip(files, col?.name ?? "api-tests", target);
|
|
45882
46228
|
}
|
|
45883
46229
|
const selectedContent = files.find((f) => f.path === selectedFile)?.content ?? "";
|
|
45884
46230
|
const activeTarget = TARGETS.find((tgt) => tgt.id === target);
|
|
@@ -46062,7 +46408,7 @@ function historyToHar(entries, creatorVersion = "1.0") {
|
|
|
46062
46408
|
}
|
|
46063
46409
|
}, null, 2);
|
|
46064
46410
|
}
|
|
46065
|
-
const { electron: electron$
|
|
46411
|
+
const { electron: electron$o } = window;
|
|
46066
46412
|
const STATUS_COLOR = {
|
|
46067
46413
|
"2": "text-emerald-400",
|
|
46068
46414
|
"3": "text-amber-400",
|
|
@@ -46116,7 +46462,7 @@ function HistoryPanel() {
|
|
|
46116
46462
|
}, [history, search]);
|
|
46117
46463
|
async function downloadHar() {
|
|
46118
46464
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replaceAll(/[:T]/g, "-");
|
|
46119
|
-
await electron$
|
|
46465
|
+
await electron$o.saveResults(historyToHar(history), `api-spector-history-${stamp}.har`);
|
|
46120
46466
|
}
|
|
46121
46467
|
function open2(entry) {
|
|
46122
46468
|
setSelected(entry);
|
|
@@ -46244,7 +46590,7 @@ function HistoryRow({
|
|
|
46244
46590
|
}
|
|
46245
46591
|
);
|
|
46246
46592
|
}
|
|
46247
|
-
const { electron: electron$
|
|
46593
|
+
const { electron: electron$n } = window;
|
|
46248
46594
|
function WelcomeScreen() {
|
|
46249
46595
|
const t = useT();
|
|
46250
46596
|
const { applyWorkspace } = useWorkspaceLoader();
|
|
@@ -46257,10 +46603,10 @@ function WelcomeScreen() {
|
|
|
46257
46603
|
const busyRef = reactExports.useRef(false);
|
|
46258
46604
|
const [busy, setBusy] = reactExports.useState(false);
|
|
46259
46605
|
reactExports.useEffect(() => {
|
|
46260
|
-
electron$
|
|
46261
|
-
electron$
|
|
46606
|
+
electron$n.getRecentWorkspaces().then(setRecents).catch(() => setRecents([]));
|
|
46607
|
+
electron$n.getUpdateMode().then((mode) => {
|
|
46262
46608
|
if (mode !== "npm") return;
|
|
46263
|
-
return electron$
|
|
46609
|
+
return electron$n.checkForUpdate().then((info) => {
|
|
46264
46610
|
if (info?.updateAvailable) setUpdate(info);
|
|
46265
46611
|
});
|
|
46266
46612
|
}).catch(() => {
|
|
@@ -46271,7 +46617,7 @@ function WelcomeScreen() {
|
|
|
46271
46617
|
busyRef.current = true;
|
|
46272
46618
|
setBusy(true);
|
|
46273
46619
|
try {
|
|
46274
|
-
const result = await electron$
|
|
46620
|
+
const result = await electron$n.openWorkspace();
|
|
46275
46621
|
if (result) await applyWorkspace(result.workspace, result.workspacePath);
|
|
46276
46622
|
} finally {
|
|
46277
46623
|
busyRef.current = false;
|
|
@@ -46283,7 +46629,7 @@ function WelcomeScreen() {
|
|
|
46283
46629
|
busyRef.current = true;
|
|
46284
46630
|
setBusy(true);
|
|
46285
46631
|
try {
|
|
46286
|
-
const result = await electron$
|
|
46632
|
+
const result = await electron$n.newWorkspace();
|
|
46287
46633
|
if (result) await applyWorkspace(result.workspace, result.workspacePath);
|
|
46288
46634
|
} finally {
|
|
46289
46635
|
busyRef.current = false;
|
|
@@ -46297,7 +46643,7 @@ function WelcomeScreen() {
|
|
|
46297
46643
|
setGitBusy(true);
|
|
46298
46644
|
setGitError(null);
|
|
46299
46645
|
try {
|
|
46300
|
-
const result = await electron$
|
|
46646
|
+
const result = await electron$n.openFromGit(url);
|
|
46301
46647
|
if (!result) return;
|
|
46302
46648
|
await applyWorkspace(result.workspace, result.workspacePath);
|
|
46303
46649
|
} catch (err) {
|
|
@@ -46312,7 +46658,7 @@ function WelcomeScreen() {
|
|
|
46312
46658
|
busyRef.current = true;
|
|
46313
46659
|
setBusy(true);
|
|
46314
46660
|
try {
|
|
46315
|
-
const result = await electron$
|
|
46661
|
+
const result = await electron$n.openWorkspacePath(path);
|
|
46316
46662
|
if (!result) {
|
|
46317
46663
|
setRecents((prev) => prev.filter((r) => r.path !== path));
|
|
46318
46664
|
return;
|
|
@@ -46348,7 +46694,7 @@ function WelcomeScreen() {
|
|
|
46348
46694
|
)
|
|
46349
46695
|
] }),
|
|
46350
46696
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-surface-400 text-sm max-w-sm", children: t("Local-first API testing with Robot Framework & Playwright code generation. Secrets stay on your machine.") }),
|
|
46351
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] mt-3", style: { color: "var(--text-muted)" }, children: t("version :version", { version: "0.9.
|
|
46697
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] mt-3", style: { color: "var(--text-muted)" }, children: t("version :version", { version: "0.9.2" }) })
|
|
46352
46698
|
] }),
|
|
46353
46699
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3 w-64", children: [
|
|
46354
46700
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -46430,7 +46776,7 @@ function WelcomeScreen() {
|
|
|
46430
46776
|
] })
|
|
46431
46777
|
] });
|
|
46432
46778
|
}
|
|
46433
|
-
const { electron: electron$
|
|
46779
|
+
const { electron: electron$m } = window;
|
|
46434
46780
|
const EXAMPLES = [
|
|
46435
46781
|
{
|
|
46436
46782
|
label: "macOS / Linux (~/.zshrc or ~/.bashrc)",
|
|
@@ -46455,7 +46801,7 @@ function MasterKeyModal({ onSuccess, onCancel }) {
|
|
|
46455
46801
|
setError(t("Password cannot be empty."));
|
|
46456
46802
|
return;
|
|
46457
46803
|
}
|
|
46458
|
-
await electron$
|
|
46804
|
+
await electron$m.setMasterKey(password);
|
|
46459
46805
|
onSuccess(password);
|
|
46460
46806
|
}
|
|
46461
46807
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
@@ -46534,7 +46880,7 @@ function MasterKeyModal({ onSuccess, onCancel }) {
|
|
|
46534
46880
|
}
|
|
46535
46881
|
);
|
|
46536
46882
|
}
|
|
46537
|
-
const { electron: electron$
|
|
46883
|
+
const { electron: electron$l } = window;
|
|
46538
46884
|
async function shortHash(value2) {
|
|
46539
46885
|
const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value2));
|
|
46540
46886
|
return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 8);
|
|
@@ -46649,12 +46995,12 @@ function EnvironmentEditor({ onClose }) {
|
|
|
46649
46995
|
if (next) setSelectedId(next);
|
|
46650
46996
|
}
|
|
46651
46997
|
async function importFromPostman() {
|
|
46652
|
-
const imported = await electron$
|
|
46998
|
+
const imported = await electron$l.importPostmanEnvironment();
|
|
46653
46999
|
if (!imported) return;
|
|
46654
47000
|
const existingNames = Object.values(useStore$1.getState().environments).map((e) => e.data.name);
|
|
46655
47001
|
const finalEnv = { ...imported, name: uniqueName$1(imported.name || t("Imported Environment"), existingNames) };
|
|
46656
47002
|
const relPath = envRelPath(finalEnv.name, finalEnv.id);
|
|
46657
|
-
await electron$
|
|
47003
|
+
await electron$l.saveEnvironment(relPath, finalEnv);
|
|
46658
47004
|
useStore$1.setState((s) => {
|
|
46659
47005
|
s.environments[finalEnv.id] = { relPath, data: finalEnv };
|
|
46660
47006
|
if (!s.activeEnvironmentId) s.activeEnvironmentId = finalEnv.id;
|
|
@@ -46664,7 +47010,7 @@ function EnvironmentEditor({ onClose }) {
|
|
|
46664
47010
|
return s;
|
|
46665
47011
|
});
|
|
46666
47012
|
const ws = useStore$1.getState().workspace;
|
|
46667
|
-
if (ws) await electron$
|
|
47013
|
+
if (ws) await electron$l.saveWorkspace(ws);
|
|
46668
47014
|
setSelectedId(finalEnv.id);
|
|
46669
47015
|
}
|
|
46670
47016
|
function updateVar(idx, patch) {
|
|
@@ -46717,9 +47063,9 @@ function EnvironmentEditor({ onClose }) {
|
|
|
46717
47063
|
async function saveEncrypted(idx) {
|
|
46718
47064
|
const plaintext = secretInputs[idx] ?? "";
|
|
46719
47065
|
if (!plaintext) return;
|
|
46720
|
-
const { set: set2 } = await electron$
|
|
47066
|
+
const { set: set2 } = await electron$l.checkMasterKey();
|
|
46721
47067
|
if (set2) {
|
|
46722
|
-
applyEncrypted(idx, await electron$
|
|
47068
|
+
applyEncrypted(idx, await electron$l.encryptWithMasterKey(plaintext));
|
|
46723
47069
|
return;
|
|
46724
47070
|
}
|
|
46725
47071
|
setPendingEncryptIdx(idx);
|
|
@@ -46754,9 +47100,9 @@ function EnvironmentEditor({ onClose }) {
|
|
|
46754
47100
|
} : state.workspace
|
|
46755
47101
|
}));
|
|
46756
47102
|
const ws = useStore$1.getState().workspace;
|
|
46757
|
-
if (ws) await electron$
|
|
47103
|
+
if (ws) await electron$l.saveWorkspace(ws);
|
|
46758
47104
|
}
|
|
46759
|
-
await electron$
|
|
47105
|
+
await electron$l.saveEnvironment(newRelPath, env2);
|
|
46760
47106
|
}
|
|
46761
47107
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
46762
47108
|
confirmDialog,
|
|
@@ -47121,7 +47467,7 @@ function EnvironmentEditor({ onClose }) {
|
|
|
47121
47467
|
)
|
|
47122
47468
|
] });
|
|
47123
47469
|
}
|
|
47124
|
-
const { electron: electron$
|
|
47470
|
+
const { electron: electron$k } = window;
|
|
47125
47471
|
function EnvironmentBar({ inline = false }) {
|
|
47126
47472
|
const t = useT();
|
|
47127
47473
|
const environments = useStore$1((s) => s.environments);
|
|
@@ -47137,7 +47483,7 @@ function EnvironmentBar({ inline = false }) {
|
|
|
47137
47483
|
if (id2) {
|
|
47138
47484
|
const hasSecrets = environments[id2]?.data.variables.some((v) => v.enabled && v.secret);
|
|
47139
47485
|
if (hasSecrets) {
|
|
47140
|
-
const { set: set2 } = await electron$
|
|
47486
|
+
const { set: set2 } = await electron$k.checkMasterKey();
|
|
47141
47487
|
if (!set2) {
|
|
47142
47488
|
setPendingEnvId(id2);
|
|
47143
47489
|
return;
|
|
@@ -47344,10 +47690,204 @@ function ProductTour() {
|
|
|
47344
47690
|
)
|
|
47345
47691
|
] });
|
|
47346
47692
|
}
|
|
47693
|
+
const { electron: electron$j } = window;
|
|
47694
|
+
function getSyncSettings() {
|
|
47695
|
+
return useStore$1.getState().workspace?.settings?.sync ?? { mode: "git" };
|
|
47696
|
+
}
|
|
47697
|
+
async function persistSync(patch) {
|
|
47698
|
+
const s = useStore$1.getState();
|
|
47699
|
+
const ws = s.workspace;
|
|
47700
|
+
if (!ws) return;
|
|
47701
|
+
const sync = { ...ws.settings?.sync ?? { mode: "cloud" }, ...patch };
|
|
47702
|
+
const settings = { ...ws.settings, sync };
|
|
47703
|
+
s.updateWorkspaceSettings(settings);
|
|
47704
|
+
await electron$j.saveWorkspace({ ...ws, settings });
|
|
47705
|
+
}
|
|
47706
|
+
async function setSyncMode(mode) {
|
|
47707
|
+
await persistSync({ mode });
|
|
47708
|
+
}
|
|
47709
|
+
function workspaceName(manifestName) {
|
|
47710
|
+
return manifestName.replace(/\.(spector|json)$/i, "") || "Workspace";
|
|
47711
|
+
}
|
|
47712
|
+
async function flushToDisk() {
|
|
47713
|
+
const s = useStore$1.getState();
|
|
47714
|
+
for (const { relPath, data, dirty } of Object.values(s.collections)) {
|
|
47715
|
+
if (!dirty) continue;
|
|
47716
|
+
await electron$j.saveCollection(relPath, data);
|
|
47717
|
+
s.markCollectionClean(data.id);
|
|
47718
|
+
}
|
|
47719
|
+
for (const { relPath, data } of Object.values(s.environments)) {
|
|
47720
|
+
await electron$j.saveEnvironment(relPath, data);
|
|
47721
|
+
}
|
|
47722
|
+
for (const { relPath, data } of Object.values(s.flows)) {
|
|
47723
|
+
await electron$j.saveFlow(relPath, data);
|
|
47724
|
+
}
|
|
47725
|
+
if (s.workspace) await electron$j.saveWorkspace(s.workspace);
|
|
47726
|
+
}
|
|
47727
|
+
async function pushWorkspace() {
|
|
47728
|
+
const sync = getSyncSettings();
|
|
47729
|
+
await flushToDisk();
|
|
47730
|
+
const snap = await electron$j.serializeWorkspace();
|
|
47731
|
+
const files = snap.files ?? {};
|
|
47732
|
+
const collections = Object.keys(files).filter((p) => p.startsWith("collections/")).length;
|
|
47733
|
+
const flows = Object.keys(files).filter((p) => p.startsWith("flows/")).length;
|
|
47734
|
+
if (!sync.cloudWorkspaceId) {
|
|
47735
|
+
const created = await electron$j.cloudWorkspaceCreate({ name: workspaceName(snap.manifestName), payload: snap });
|
|
47736
|
+
await persistSync({ mode: "cloud", cloudWorkspaceId: created.id, baseVersion: created.version });
|
|
47737
|
+
return { ok: true, version: created.version, collections, flows };
|
|
47738
|
+
}
|
|
47739
|
+
const res = await electron$j.cloudWorkspacePush({
|
|
47740
|
+
id: sync.cloudWorkspaceId,
|
|
47741
|
+
baseVersion: sync.baseVersion ?? 0,
|
|
47742
|
+
payload: snap
|
|
47743
|
+
});
|
|
47744
|
+
if (res.conflict) return { ok: false, conflict: true, currentVersion: res.currentVersion };
|
|
47745
|
+
await persistSync({ baseVersion: res.version });
|
|
47746
|
+
return { ok: true, version: res.version ?? 0, collections, flows };
|
|
47747
|
+
}
|
|
47748
|
+
async function pullWorkspace() {
|
|
47749
|
+
const sync = getSyncSettings();
|
|
47750
|
+
if (!sync.cloudWorkspaceId) {
|
|
47751
|
+
throw new Error("This workspace is not linked to a cloud workspace yet. Push it first, or link an existing one.");
|
|
47752
|
+
}
|
|
47753
|
+
const remote = await electron$j.cloudWorkspacePull(sync.cloudWorkspaceId);
|
|
47754
|
+
const payload = remote.payload ?? {};
|
|
47755
|
+
if (!payload.manifest || !payload.files) {
|
|
47756
|
+
throw new Error("The cloud workspace has no snapshot yet. Push from a populated workspace first.");
|
|
47757
|
+
}
|
|
47758
|
+
const applied = await electron$j.applyWorkspaceSnapshot({ manifest: payload.manifest, files: payload.files });
|
|
47759
|
+
return {
|
|
47760
|
+
version: remote.version,
|
|
47761
|
+
filesWritten: applied.filesWritten,
|
|
47762
|
+
collections: applied.collections,
|
|
47763
|
+
workspace: applied.workspace,
|
|
47764
|
+
workspacePath: applied.workspacePath
|
|
47765
|
+
};
|
|
47766
|
+
}
|
|
47767
|
+
async function markPulled(version) {
|
|
47768
|
+
await persistSync({ baseVersion: version });
|
|
47769
|
+
}
|
|
47770
|
+
async function listCloudWorkspaces() {
|
|
47771
|
+
const res = await electron$j.cloudWorkspaceList();
|
|
47772
|
+
return res.workspaces;
|
|
47773
|
+
}
|
|
47774
|
+
async function linkToCloudWorkspace(id2) {
|
|
47775
|
+
await persistSync({ mode: "cloud", cloudWorkspaceId: id2, baseVersion: 0 });
|
|
47776
|
+
}
|
|
47777
|
+
function SyncSettingsPanel() {
|
|
47778
|
+
const t = useT();
|
|
47779
|
+
const { applyWorkspace } = useWorkspaceLoader();
|
|
47780
|
+
const initial = getSyncSettings();
|
|
47781
|
+
const [mode, setMode] = reactExports.useState(initial.mode);
|
|
47782
|
+
const [linked, setLinked] = reactExports.useState(!!initial.cloudWorkspaceId);
|
|
47783
|
+
const [busy, setBusy] = reactExports.useState(false);
|
|
47784
|
+
const [status, setStatus] = reactExports.useState(null);
|
|
47785
|
+
const [remote, setRemote] = reactExports.useState(null);
|
|
47786
|
+
const cloudOn = cloudEnabled();
|
|
47787
|
+
async function changeMode(m) {
|
|
47788
|
+
setMode(m);
|
|
47789
|
+
setStatus(null);
|
|
47790
|
+
try {
|
|
47791
|
+
await setSyncMode(m);
|
|
47792
|
+
} catch (e) {
|
|
47793
|
+
setStatus({ msg: e.message, ok: false });
|
|
47794
|
+
}
|
|
47795
|
+
}
|
|
47796
|
+
async function run(fn) {
|
|
47797
|
+
setBusy(true);
|
|
47798
|
+
setStatus(null);
|
|
47799
|
+
try {
|
|
47800
|
+
setStatus({ msg: await fn(), ok: true });
|
|
47801
|
+
} catch (e) {
|
|
47802
|
+
setStatus({ msg: e.message, ok: false });
|
|
47803
|
+
} finally {
|
|
47804
|
+
setBusy(false);
|
|
47805
|
+
}
|
|
47806
|
+
}
|
|
47807
|
+
const doPush = () => run(async () => {
|
|
47808
|
+
const res = await pushWorkspace();
|
|
47809
|
+
if (!res.ok) throw new Error(t("Someone else pushed changes (cloud is at v:v). Pull first, then push again.", { v: res.currentVersion ?? "?" }));
|
|
47810
|
+
setLinked(true);
|
|
47811
|
+
return t("Pushed :c collection(s) and :f flow(s). Cloud is now at version :v.", { c: res.collections, f: res.flows, v: res.version });
|
|
47812
|
+
});
|
|
47813
|
+
const doPull = () => run(async () => {
|
|
47814
|
+
const r = await pullWorkspace();
|
|
47815
|
+
await applyWorkspace(r.workspace, r.workspacePath);
|
|
47816
|
+
await markPulled(r.version);
|
|
47817
|
+
return t("Pulled version :v: :files file(s), :c collection(s).", { v: r.version, files: r.filesWritten, c: r.collections });
|
|
47818
|
+
});
|
|
47819
|
+
const loadRemote = () => run(async () => {
|
|
47820
|
+
const list = await listCloudWorkspaces();
|
|
47821
|
+
setRemote(list);
|
|
47822
|
+
return t(":n cloud workspace(s) in your organization.", { n: list.length });
|
|
47823
|
+
});
|
|
47824
|
+
const joinExisting = (id2) => run(async () => {
|
|
47825
|
+
await linkToCloudWorkspace(id2);
|
|
47826
|
+
const r = await pullWorkspace();
|
|
47827
|
+
await applyWorkspace(r.workspace, r.workspacePath);
|
|
47828
|
+
await markPulled(r.version);
|
|
47829
|
+
setLinked(true);
|
|
47830
|
+
return t("Linked and pulled: :files file(s), :c collection(s).", { files: r.filesWritten, c: r.collections });
|
|
47831
|
+
});
|
|
47832
|
+
const btn = "px-3 py-1.5 text-xs rounded border border-surface-700 text-surface-200 hover:bg-surface-800 disabled:opacity-50 transition-colors";
|
|
47833
|
+
const btnPrimary = "px-3 py-1.5 text-xs rounded font-medium text-white bg-sky-700 hover:bg-sky-600 disabled:opacity-50 transition-colors";
|
|
47834
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-5 text-sm text-surface-200", children: [
|
|
47835
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
47836
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "font-semibold text-[var(--text-primary)]", children: t("Workspace sync") }),
|
|
47837
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-400 mt-1", children: t("How this workspace is shared with your team. Git is the default; Cloud lets teams without git collaborate.") })
|
|
47838
|
+
] }),
|
|
47839
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
47840
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs uppercase tracking-wide text-surface-500", children: t("Mode") }),
|
|
47841
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47842
|
+
"select",
|
|
47843
|
+
{
|
|
47844
|
+
value: mode,
|
|
47845
|
+
onChange: (e) => changeMode(e.target.value),
|
|
47846
|
+
className: "rounded bg-surface-950 border border-surface-700 px-2 py-1.5 text-sm w-56",
|
|
47847
|
+
children: [
|
|
47848
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "git", children: t("Git (default) — use the Git panel") }),
|
|
47849
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "cloud", children: t("Cloud — sync through API Spector Cloud") }),
|
|
47850
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "local", children: t("Local only — no sync") })
|
|
47851
|
+
]
|
|
47852
|
+
}
|
|
47853
|
+
)
|
|
47854
|
+
] }),
|
|
47855
|
+
mode === "git" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-400", children: t("This workspace syncs via Git. Use the Git panel in the sidebar to commit, pull and push.") }),
|
|
47856
|
+
mode === "local" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-400", children: t("No syncing. Changes stay on this machine.") }),
|
|
47857
|
+
mode === "cloud" && !cloudOn && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-amber-400", children: t("Connect this workspace to API Spector Cloud first (the Cloud tab), then come back to sync.") }),
|
|
47858
|
+
mode === "cloud" && cloudOn && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
47859
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-500", children: t("Collections, folders, requests, flows and environments sync. Secret values are never uploaded — each member keeps their own.") }),
|
|
47860
|
+
linked ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
47861
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: btnPrimary, disabled: busy, onClick: doPush, children: t("Push") }),
|
|
47862
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: btn, disabled: busy, onClick: doPull, children: t("Pull") })
|
|
47863
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
47864
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
47865
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: btnPrimary, disabled: busy, onClick: doPush, children: t("Create cloud workspace (push)") }),
|
|
47866
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: btn, disabled: busy, onClick: loadRemote, children: t("Join an existing one") })
|
|
47867
|
+
] }),
|
|
47868
|
+
remote && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded border border-surface-700 divide-y divide-surface-800", children: [
|
|
47869
|
+
remote.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-2 text-xs text-surface-500", children: t("No cloud workspaces yet.") }),
|
|
47870
|
+
remote.map((w) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 px-3 py-2", children: [
|
|
47871
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex-1 truncate", children: [
|
|
47872
|
+
w.name,
|
|
47873
|
+
" ",
|
|
47874
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-500", children: [
|
|
47875
|
+
"v",
|
|
47876
|
+
w.version
|
|
47877
|
+
] })
|
|
47878
|
+
] }),
|
|
47879
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: btn, disabled: busy, onClick: () => joinExisting(w.id), children: t("Join & pull") })
|
|
47880
|
+
] }, w.id))
|
|
47881
|
+
] })
|
|
47882
|
+
] })
|
|
47883
|
+
] }),
|
|
47884
|
+
status && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: `text-xs ${status.ok ? "text-emerald-400" : "text-red-400"}`, children: status.msg })
|
|
47885
|
+
] });
|
|
47886
|
+
}
|
|
47347
47887
|
const { electron: electron$i } = window;
|
|
47348
47888
|
const DEFAULT_PII_PATTERNS = ["authorization", "password", "token", "secret", "api-key", "x-api-key"];
|
|
47349
47889
|
const ZOOM_STEPS = [0.75, 0.9, 1, 1.1, 1.25, 1.5];
|
|
47350
|
-
const SETTINGS_TABS = ["general", "appearance", "proxy", "tls", "privacy", "cloud", "ai", "secrets"];
|
|
47890
|
+
const SETTINGS_TABS = ["general", "appearance", "proxy", "tls", "privacy", "cloud", "sync", "ai", "secrets"];
|
|
47351
47891
|
function WorkspaceSettingsModal({ onClose, initialTab }) {
|
|
47352
47892
|
const workspace = useStore$1((s) => s.workspace);
|
|
47353
47893
|
const updateWorkspaceSettings = useStore$1((s) => s.updateWorkspaceSettings);
|
|
@@ -47555,6 +48095,7 @@ function WorkspaceSettingsModal({ onClose, initialTab }) {
|
|
|
47555
48095
|
{ id: "privacy", label: t("Privacy") },
|
|
47556
48096
|
{ id: "secrets", label: t("Secrets") },
|
|
47557
48097
|
{ id: "cloud", label: t("Cloud") },
|
|
48098
|
+
{ id: "sync", label: t("Sync") },
|
|
47558
48099
|
{ id: "ai", label: t("AI") }
|
|
47559
48100
|
];
|
|
47560
48101
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
@@ -47879,6 +48420,7 @@ function WorkspaceSettingsModal({ onClose, initialTab }) {
|
|
|
47879
48420
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t("Reject unauthorized / self-signed certificates") })
|
|
47880
48421
|
] })
|
|
47881
48422
|
] }),
|
|
48423
|
+
activeTab === "sync" && /* @__PURE__ */ jsxRuntimeExports.jsx(SyncSettingsPanel, {}),
|
|
47882
48424
|
activeTab === "ai" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
47883
48425
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-surface-600 text-[11px] leading-relaxed", children: t("Optional. Configure an OpenAI key to generate documentation from the Docs tab of a request, folder, or collection. The key is stored only in your OS keychain and never written to the workspace file or version control.") }),
|
|
47884
48426
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
@@ -47965,10 +48507,17 @@ function WorkspaceSettingsModal({ onClose, initialTab }) {
|
|
|
47965
48507
|
" ",
|
|
47966
48508
|
t("in an environment variable or an auth field; it is resolved at send-time and never written to the workspace. This connection config is non-secret - tokens and secret-ids come from your environment (or the Vault sign-in below).")
|
|
47967
48509
|
] }),
|
|
48510
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-surface-600 text-[11px]", children: [
|
|
48511
|
+
t("Using OpenBao? It is API-compatible, so the same settings apply. Reference secrets with"),
|
|
48512
|
+
" ",
|
|
48513
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-surface-400", children: "bao:secret/data/app#token" }),
|
|
48514
|
+
" ",
|
|
48515
|
+
t("and set BAO_ADDR / BAO_TOKEN (VAULT_* also works).")
|
|
48516
|
+
] }),
|
|
47968
48517
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 border border-surface-800 rounded p-3", children: [
|
|
47969
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase tracking-wider text-surface-500 font-semibold", children: "HashiCorp Vault" }),
|
|
48518
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase tracking-wider text-surface-500 font-semibold", children: t("HashiCorp Vault / OpenBao") }),
|
|
47970
48519
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
47971
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: labelCls, children: t("Address (VAULT_ADDR)") }),
|
|
48520
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: labelCls, children: t("Address (VAULT_ADDR / BAO_ADDR)") }),
|
|
47972
48521
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47973
48522
|
"input",
|
|
47974
48523
|
{
|
|
@@ -49249,6 +49798,46 @@ function collectRequestsByFolder(folder2, src) {
|
|
|
49249
49798
|
walk2(folder2);
|
|
49250
49799
|
return out;
|
|
49251
49800
|
}
|
|
49801
|
+
function Tooltip({
|
|
49802
|
+
label,
|
|
49803
|
+
align = "center",
|
|
49804
|
+
children: children2
|
|
49805
|
+
}) {
|
|
49806
|
+
const pos = align === "right" ? "right-0" : align === "left" ? "left-0" : "left-1/2 -translate-x-1/2";
|
|
49807
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "relative inline-flex group/tip", children: [
|
|
49808
|
+
children2,
|
|
49809
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49810
|
+
"span",
|
|
49811
|
+
{
|
|
49812
|
+
"aria-hidden": "true",
|
|
49813
|
+
className: `pointer-events-none absolute top-full ${pos} mt-1.5 z-50 hidden group-hover/tip:block group-focus-within/tip:block whitespace-nowrap rounded px-2 py-1 text-[11px] bg-surface-900 text-[var(--text-primary)] border border-surface-700 shadow-lg`,
|
|
49814
|
+
children: label
|
|
49815
|
+
}
|
|
49816
|
+
)
|
|
49817
|
+
] });
|
|
49818
|
+
}
|
|
49819
|
+
function DocIcon() {
|
|
49820
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", strokeWidth: 1.8, viewBox: "0 0 24 24", "aria-hidden": "true", children: [
|
|
49821
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M14 3H7a2 2 0 00-2 2v14a2 2 0 002 2h10a2 2 0 002-2V8l-5-5z" }),
|
|
49822
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M14 3v5h5M8.5 13h7M8.5 16.5h5" })
|
|
49823
|
+
] });
|
|
49824
|
+
}
|
|
49825
|
+
function ImportIcon() {
|
|
49826
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", strokeWidth: 1.8, viewBox: "0 0 24 24", "aria-hidden": "true", children: [
|
|
49827
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 3v10m0 0l-3.5-3.5M12 13l3.5-3.5" }),
|
|
49828
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4 16v3a2 2 0 002 2h12a2 2 0 002-2v-3" })
|
|
49829
|
+
] });
|
|
49830
|
+
}
|
|
49831
|
+
function Svg({ children: children2 }) {
|
|
49832
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { className: "w-3 h-3", fill: "none", stroke: "currentColor", strokeWidth: 1.8, viewBox: "0 0 24 24", "aria-hidden": "true", children: children2 });
|
|
49833
|
+
}
|
|
49834
|
+
const OpenWsIcon = () => /* @__PURE__ */ jsxRuntimeExports.jsx(Svg, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 9.75h16.5a1.5 1.5 0 011.47 1.8l-1.2 6a1.5 1.5 0 01-1.47 1.2H4.95a1.5 1.5 0 01-1.47-1.2l-1.2-6a1.5 1.5 0 011.47-1.8zM3.75 9.75V6.75A1.5 1.5 0 015.25 5.25h3.88a1.5 1.5 0 011.06.44l1.12 1.12a1.5 1.5 0 001.06.44h4.88a1.5 1.5 0 011.5 1.5v.56" }) });
|
|
49835
|
+
const NewWsIcon = () => /* @__PURE__ */ jsxRuntimeExports.jsx(Svg, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 11v5m2.5-2.5h-5M3.75 7.5V18a1.5 1.5 0 001.5 1.5h13.5A1.5 1.5 0 0020.25 18V9a1.5 1.5 0 00-1.5-1.5h-5.19a1.5 1.5 0 01-1.06-.44l-1.12-1.12a1.5 1.5 0 00-1.06-.44H5.25a1.5 1.5 0 00-1.5 1.5z" }) });
|
|
49836
|
+
const CloseWsIcon = () => /* @__PURE__ */ jsxRuntimeExports.jsx(Svg, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M18 6L6 18" }) });
|
|
49837
|
+
const SaveIcon = () => /* @__PURE__ */ jsxRuntimeExports.jsxs(Svg, { children: [
|
|
49838
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 4h11l3 3v12a1 1 0 01-1 1H5a1 1 0 01-1-1V5a1 1 0 011-1z" }),
|
|
49839
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8 4v4h6V4M8 13h8v6H8z" })
|
|
49840
|
+
] });
|
|
49252
49841
|
const { electron: electron$f } = window;
|
|
49253
49842
|
function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
49254
49843
|
const t = useT();
|
|
@@ -49360,34 +49949,51 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
49360
49949
|
.logo-pupil-r { animation-delay: 0.04s; }
|
|
49361
49950
|
` }),
|
|
49362
49951
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 mr-1 shrink-0 select-none", children: [
|
|
49363
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
49364
|
-
|
|
49365
|
-
|
|
49366
|
-
|
|
49367
|
-
|
|
49368
|
-
|
|
49369
|
-
|
|
49370
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("
|
|
49371
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
49372
|
-
|
|
49373
|
-
|
|
49374
|
-
|
|
49375
|
-
|
|
49376
|
-
|
|
49377
|
-
|
|
49378
|
-
|
|
49379
|
-
|
|
49380
|
-
|
|
49381
|
-
|
|
49382
|
-
|
|
49383
|
-
|
|
49384
|
-
|
|
49952
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49953
|
+
"button",
|
|
49954
|
+
{
|
|
49955
|
+
onClick: () => window.electron.openExternal("https://api-spector.dev"),
|
|
49956
|
+
title: t("Open api-spector.dev"),
|
|
49957
|
+
"aria-label": t("API Spector home"),
|
|
49958
|
+
className: "shrink-0 focus:outline-none rounded hover:opacity-80 transition-opacity cursor-pointer",
|
|
49959
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "52", height: "52", viewBox: "0 0 512 512", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
49960
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("defs", { children: [
|
|
49961
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("radialGradient", { id: "logoBody", cx: "35%", cy: "22%", r: "70%", children: [
|
|
49962
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "0%", stopColor: "#5497c8" }),
|
|
49963
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "55%", stopColor: "#205d96" }),
|
|
49964
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "100%", stopColor: "#123a60" })
|
|
49965
|
+
] }),
|
|
49966
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("linearGradient", { id: "logoGloss", x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
49967
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "0%", stopColor: "white", stopOpacity: "0.45" }),
|
|
49968
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "100%", stopColor: "white", stopOpacity: "0" })
|
|
49969
|
+
] }),
|
|
49970
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("clipPath", { id: "logoGhostClip", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M 130,225 C 130,95 382,95 382,225 L 382,390 Q 340,435 298,390 Q 256,435 214,390 Q 172,435 130,390 Z" }) })
|
|
49971
|
+
] }),
|
|
49972
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M 130,225 C 130,95 382,95 382,225 L 382,390 Q 340,435 298,390 Q 256,435 214,390 Q 172,435 130,390 Z", fill: "url(#logoBody)" }),
|
|
49973
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("ellipse", { cx: "198", cy: "262", rx: "29", ry: "33", fill: "white" }),
|
|
49974
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("ellipse", { cx: "314", cy: "262", rx: "29", ry: "33", fill: "white" }),
|
|
49975
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("ellipse", { cx: "204", cy: "268", rx: "16", ry: "20", fill: "#0b1624", className: "logo-pupil" }),
|
|
49976
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("ellipse", { cx: "320", cy: "268", rx: "16", ry: "20", fill: "#0b1624", className: "logo-pupil logo-pupil-r" }),
|
|
49977
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("ellipse", { cx: "194", cy: "254", rx: "6", ry: "7", fill: "white", opacity: "0.65" }),
|
|
49978
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("ellipse", { cx: "310", cy: "254", rx: "6", ry: "7", fill: "white", opacity: "0.65" }),
|
|
49979
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("ellipse", { cx: "256", cy: "100", rx: "200", ry: "180", fill: "url(#logoGloss)", clipPath: "url(#logoGhostClip)" })
|
|
49980
|
+
] })
|
|
49981
|
+
}
|
|
49982
|
+
),
|
|
49385
49983
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col leading-tight", children: [
|
|
49386
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49387
|
-
|
|
49388
|
-
|
|
49389
|
-
|
|
49390
|
-
|
|
49984
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49985
|
+
"button",
|
|
49986
|
+
{
|
|
49987
|
+
onClick: () => window.electron.openExternal("https://api-spector.dev"),
|
|
49988
|
+
title: t("Open api-spector.dev"),
|
|
49989
|
+
className: "text-xs font-semibold tracking-wide text-left hover:underline focus:outline-none cursor-pointer",
|
|
49990
|
+
children: [
|
|
49991
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--wordmark-muted)" }, children: "API" }),
|
|
49992
|
+
" ",
|
|
49993
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--wordmark-accent)" }, children: "Spector" })
|
|
49994
|
+
]
|
|
49995
|
+
}
|
|
49996
|
+
),
|
|
49391
49997
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49392
49998
|
"button",
|
|
49393
49999
|
{
|
|
@@ -49399,92 +50005,98 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
49399
50005
|
)
|
|
49400
50006
|
] })
|
|
49401
50007
|
] }),
|
|
49402
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49403
|
-
"button",
|
|
49404
|
-
{
|
|
49405
|
-
onClick: () => setImportOpen(true),
|
|
49406
|
-
className: "px-2.5 py-1 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors shrink-0",
|
|
49407
|
-
title: t("Import collection (Postman, OpenAPI, Insomnia, Bruno)"),
|
|
49408
|
-
children: t("Import")
|
|
49409
|
-
}
|
|
49410
|
-
),
|
|
49411
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-4 bg-surface-800 mx-1 shrink-0" }),
|
|
49412
50008
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-xs shrink-0", children: t("ENV") }),
|
|
49413
50009
|
/* @__PURE__ */ jsxRuntimeExports.jsx(EnvironmentBar, { inline: true })
|
|
49414
50010
|
] }),
|
|
49415
50011
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 px-3 py-1.5 shrink-0 border-l border-surface-800", children: [
|
|
49416
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50012
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-xs shrink-0", children: t("Workspace") }),
|
|
50013
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { label: t("Open a different workspace"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49417
50014
|
"button",
|
|
49418
50015
|
{
|
|
49419
50016
|
onClick: openWs,
|
|
49420
50017
|
disabled: wsBusy,
|
|
49421
|
-
className: "
|
|
49422
|
-
|
|
49423
|
-
children:
|
|
50018
|
+
className: "p-1.5 bg-surface-800 hover:bg-surface-700 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
50019
|
+
"aria-label": t("Open a different workspace"),
|
|
50020
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(OpenWsIcon, {})
|
|
49424
50021
|
}
|
|
49425
|
-
),
|
|
49426
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50022
|
+
) }),
|
|
50023
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { label: t("Create a new workspace"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49427
50024
|
"button",
|
|
49428
50025
|
{
|
|
49429
50026
|
onClick: newWs,
|
|
49430
50027
|
disabled: wsBusy,
|
|
49431
|
-
className: "
|
|
49432
|
-
|
|
49433
|
-
children:
|
|
50028
|
+
className: "p-1.5 bg-surface-800 hover:bg-surface-700 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
50029
|
+
"aria-label": t("Create a new workspace"),
|
|
50030
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(NewWsIcon, {})
|
|
49434
50031
|
}
|
|
49435
|
-
),
|
|
49436
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50032
|
+
) }),
|
|
50033
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { label: t("Close current workspace"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49437
50034
|
"button",
|
|
49438
50035
|
{
|
|
49439
50036
|
onClick: async () => {
|
|
49440
50037
|
await electron$f.closeWorkspace();
|
|
49441
50038
|
closeWorkspace();
|
|
49442
50039
|
},
|
|
49443
|
-
className: "
|
|
49444
|
-
|
|
49445
|
-
children:
|
|
50040
|
+
className: "p-1.5 bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
50041
|
+
"aria-label": t("Close current workspace"),
|
|
50042
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(CloseWsIcon, {})
|
|
49446
50043
|
}
|
|
49447
|
-
),
|
|
49448
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
50044
|
+
) }),
|
|
50045
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { label: saving ? t("Saving…") : t("Save all unsaved changes"), children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
49449
50046
|
"button",
|
|
49450
50047
|
{
|
|
49451
50048
|
onClick: saveAll,
|
|
49452
50049
|
disabled: saving,
|
|
49453
|
-
className: `
|
|
49454
|
-
|
|
50050
|
+
className: `relative p-1.5 rounded transition-colors ${hasDirty ? "bg-blue-700 hover:bg-blue-600 text-white" : "bg-surface-800 hover:bg-surface-700 text-surface-500"} ${saving ? "opacity-60" : ""}`,
|
|
50051
|
+
"aria-label": t("Save all unsaved changes"),
|
|
49455
50052
|
children: [
|
|
49456
|
-
|
|
49457
|
-
|
|
50053
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(SaveIcon, {}),
|
|
50054
|
+
hasDirty && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute -top-0.5 -right-0.5 w-1.5 h-1.5 rounded-full bg-amber-400" })
|
|
49458
50055
|
]
|
|
49459
50056
|
}
|
|
49460
|
-
),
|
|
49461
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49462
|
-
|
|
49463
|
-
{
|
|
49464
|
-
onClick: () => setWorkspaceSettingsOpen(true),
|
|
49465
|
-
className: "px-2.5 py-1 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
49466
|
-
title: t("Workspace settings"),
|
|
49467
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: "16px", lineHeight: 1 }, children: "⚙" })
|
|
49468
|
-
}
|
|
49469
|
-
),
|
|
49470
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50057
|
+
) }),
|
|
50058
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-4 bg-surface-800 mx-1 shrink-0" }),
|
|
50059
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { label: t("Import collection (Postman, OpenAPI, Insomnia, Bruno)"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49471
50060
|
"button",
|
|
49472
50061
|
{
|
|
49473
|
-
onClick: () =>
|
|
49474
|
-
className: "
|
|
49475
|
-
|
|
49476
|
-
children:
|
|
50062
|
+
onClick: () => setImportOpen(true),
|
|
50063
|
+
className: "p-1.5 bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
50064
|
+
"aria-label": t("Import collection (Postman, OpenAPI, Insomnia, Bruno)"),
|
|
50065
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(ImportIcon, {})
|
|
49477
50066
|
}
|
|
49478
|
-
),
|
|
49479
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50067
|
+
) }),
|
|
50068
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-4 bg-surface-800 mx-1 shrink-0" }),
|
|
50069
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1 shrink-0", children: [
|
|
50070
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-surface-600 text-xs", children: t("Generate") }),
|
|
50071
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { label: t("Generate API documentation"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50072
|
+
"button",
|
|
50073
|
+
{
|
|
50074
|
+
onClick: () => setDocsOpen(true),
|
|
50075
|
+
className: "p-1.5 bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
50076
|
+
"aria-label": t("Generate API documentation"),
|
|
50077
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(DocIcon, {})
|
|
50078
|
+
}
|
|
50079
|
+
) }),
|
|
50080
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { label: t("Toggle code generator"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
50081
|
+
"button",
|
|
50082
|
+
{
|
|
50083
|
+
onClick: () => setShowGeneratorPanel(!showGeneratorPanel),
|
|
50084
|
+
className: `px-2 py-1 text-xs font-mono rounded transition-colors ${showGeneratorPanel ? "bg-blue-700 text-white" : "bg-surface-800 hover:bg-surface-700"}`,
|
|
50085
|
+
"aria-label": t("Toggle code generator"),
|
|
50086
|
+
children: "</>"
|
|
50087
|
+
}
|
|
50088
|
+
) })
|
|
50089
|
+
] }),
|
|
50090
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-px h-4 bg-surface-800 mx-1 shrink-0" }),
|
|
50091
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { label: t("Workspace settings"), align: "right", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
49480
50092
|
"button",
|
|
49481
50093
|
{
|
|
49482
|
-
onClick: () =>
|
|
49483
|
-
className:
|
|
49484
|
-
|
|
49485
|
-
children:
|
|
50094
|
+
onClick: () => setWorkspaceSettingsOpen(true),
|
|
50095
|
+
className: "p-1.5 bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
50096
|
+
"aria-label": t("Workspace settings"),
|
|
50097
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(GearIcon, {})
|
|
49486
50098
|
}
|
|
49487
|
-
)
|
|
50099
|
+
) })
|
|
49488
50100
|
] })
|
|
49489
50101
|
] })
|
|
49490
50102
|
] });
|
|
@@ -54084,6 +54696,7 @@ function detectPlatform(remotes) {
|
|
|
54084
54696
|
const NODE_LTS = "lts/*";
|
|
54085
54697
|
const PROVIDER_ENV = {
|
|
54086
54698
|
vault: ["VAULT_ADDR", "VAULT_ROLE_ID", "VAULT_SECRET_ID"],
|
|
54699
|
+
bao: ["BAO_ADDR", "BAO_ROLE_ID", "BAO_SECRET_ID"],
|
|
54087
54700
|
aws: ["AWS_REGION", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
|
|
54088
54701
|
azure: ["AZURE_TENANT_ID", "AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET"],
|
|
54089
54702
|
gcp: ["GCP_PROJECT", "GOOGLE_APPLICATION_CREDENTIALS_JSON"],
|
|
@@ -54092,10 +54705,10 @@ const PROVIDER_ENV = {
|
|
|
54092
54705
|
function secretManagerOf(ref) {
|
|
54093
54706
|
if (ref.startsWith("op://")) return "op";
|
|
54094
54707
|
const scheme = ref.split(":", 1)[0];
|
|
54095
|
-
if (scheme === "vault" || scheme === "aws" || scheme === "azure" || scheme === "gcp") return scheme;
|
|
54708
|
+
if (scheme === "vault" || scheme === "bao" || scheme === "aws" || scheme === "azure" || scheme === "gcp") return scheme;
|
|
54096
54709
|
return null;
|
|
54097
54710
|
}
|
|
54098
|
-
const INLINE_REF_RE = /\{\{\s*(vault:|aws:|azure:|gcp:|op:\/\/)/g;
|
|
54711
|
+
const INLINE_REF_RE = /\{\{\s*(vault:|bao:|aws:|azure:|gcp:|op:\/\/)/g;
|
|
54099
54712
|
function inlineSecretManagers(text) {
|
|
54100
54713
|
if (!text) return [];
|
|
54101
54714
|
const kinds = /* @__PURE__ */ new Set();
|
|
@@ -54497,6 +55110,16 @@ function ChangesTab({ status, onRefresh }) {
|
|
|
54497
55110
|
setError(String(e));
|
|
54498
55111
|
}
|
|
54499
55112
|
}
|
|
55113
|
+
async function stash() {
|
|
55114
|
+
try {
|
|
55115
|
+
setError(null);
|
|
55116
|
+
await electron$4.gitStash();
|
|
55117
|
+
showToast(t("Changes stashed - restore them from the Branches tab"), true);
|
|
55118
|
+
onRefresh();
|
|
55119
|
+
} catch (e) {
|
|
55120
|
+
setError(String(e));
|
|
55121
|
+
}
|
|
55122
|
+
}
|
|
54500
55123
|
async function fetch() {
|
|
54501
55124
|
setFetching(true);
|
|
54502
55125
|
try {
|
|
@@ -54549,6 +55172,7 @@ function ChangesTab({ status, onRefresh }) {
|
|
|
54549
55172
|
}
|
|
54550
55173
|
const allUnstaged = [...status.unstaged, ...status.untracked];
|
|
54551
55174
|
const hasStaged = status.staged.length > 0;
|
|
55175
|
+
const isDirty = hasStaged || status.unstaged.length > 0 || status.untracked.length > 0;
|
|
54552
55176
|
const needsPush = status.ahead > 0;
|
|
54553
55177
|
const needsPull = status.behind > 0;
|
|
54554
55178
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col flex-1 min-h-0", children: [
|
|
@@ -54805,15 +55429,27 @@ function ChangesTab({ status, onRefresh }) {
|
|
|
54805
55429
|
className: "w-full bg-surface-800 border border-surface-700 rounded px-2 py-1.5 text-xs resize-none focus:outline-none focus:border-blue-500 placeholder-surface-600"
|
|
54806
55430
|
}
|
|
54807
55431
|
),
|
|
54808
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
54809
|
-
|
|
54810
|
-
|
|
54811
|
-
|
|
54812
|
-
|
|
54813
|
-
|
|
54814
|
-
|
|
54815
|
-
|
|
54816
|
-
|
|
55432
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
55433
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55434
|
+
"button",
|
|
55435
|
+
{
|
|
55436
|
+
onClick: commit,
|
|
55437
|
+
disabled: !message.trim() || !hasStaged,
|
|
55438
|
+
className: "flex-1 py-1.5 bg-blue-600 hover:bg-blue-500 disabled:opacity-40 disabled:cursor-not-allowed rounded text-xs font-medium transition-colors",
|
|
55439
|
+
children: hasStaged ? t("Commit (:count)", { count: status.staged.length }) : t("Commit")
|
|
55440
|
+
}
|
|
55441
|
+
),
|
|
55442
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55443
|
+
"button",
|
|
55444
|
+
{
|
|
55445
|
+
onClick: stash,
|
|
55446
|
+
disabled: !isDirty,
|
|
55447
|
+
title: t("Park all uncommitted changes - restore them later from the Branches tab"),
|
|
55448
|
+
className: "px-3 py-1.5 bg-surface-800 hover:bg-surface-700 border border-surface-700 disabled:opacity-40 disabled:cursor-not-allowed rounded text-xs font-medium text-surface-200 transition-colors",
|
|
55449
|
+
children: t("Stash")
|
|
55450
|
+
}
|
|
55451
|
+
)
|
|
55452
|
+
] })
|
|
54817
55453
|
] })
|
|
54818
55454
|
] });
|
|
54819
55455
|
}
|
|
@@ -54841,6 +55477,8 @@ function BranchesTab({ onRefresh }) {
|
|
|
54841
55477
|
const t = useT();
|
|
54842
55478
|
const [branches, setBranches] = reactExports.useState([]);
|
|
54843
55479
|
const [remotes, setRemotes] = reactExports.useState([]);
|
|
55480
|
+
const [stashes, setStashes] = reactExports.useState([]);
|
|
55481
|
+
const [info, setInfo] = reactExports.useState(null);
|
|
54844
55482
|
const [loading, setLoading] = reactExports.useState(true);
|
|
54845
55483
|
const [newBranch, setNewBranch] = reactExports.useState("");
|
|
54846
55484
|
const [creating, setCreating] = reactExports.useState(false);
|
|
@@ -54854,9 +55492,10 @@ function BranchesTab({ onRefresh }) {
|
|
|
54854
55492
|
const [filter2, setFilter] = reactExports.useState("");
|
|
54855
55493
|
const load2 = reactExports.useCallback(() => {
|
|
54856
55494
|
setLoadError(null);
|
|
54857
|
-
Promise.all([electron$4.gitBranches(), electron$4.gitRemotes()]).then(([b, r]) => {
|
|
55495
|
+
Promise.all([electron$4.gitBranches(), electron$4.gitRemotes(), electron$4.gitStashList()]).then(([b, r, s]) => {
|
|
54858
55496
|
setBranches(b);
|
|
54859
55497
|
setRemotes(r);
|
|
55498
|
+
setStashes(s);
|
|
54860
55499
|
}).catch((err) => {
|
|
54861
55500
|
console.warn("GitPanel: failed to load branches/remotes", err);
|
|
54862
55501
|
setLoadError(err instanceof Error ? err.message : String(err));
|
|
@@ -54865,13 +55504,34 @@ function BranchesTab({ onRefresh }) {
|
|
|
54865
55504
|
reactExports.useEffect(() => {
|
|
54866
55505
|
load2();
|
|
54867
55506
|
}, [load2]);
|
|
55507
|
+
function isDirtyTreeError(msg) {
|
|
55508
|
+
return /overwritten by (checkout|merge)|commit your changes or stash/i.test(msg);
|
|
55509
|
+
}
|
|
55510
|
+
async function checkoutOrStash(localName, create2) {
|
|
55511
|
+
try {
|
|
55512
|
+
await electron$4.gitCheckout(localName, create2);
|
|
55513
|
+
return true;
|
|
55514
|
+
} catch (e) {
|
|
55515
|
+
const msg = String(e);
|
|
55516
|
+
if (!isDirtyTreeError(msg)) throw e;
|
|
55517
|
+
if (!confirm(t('You have uncommitted changes that would be lost switching to ":name". Stash them and switch?', { name: localName }))) {
|
|
55518
|
+
return false;
|
|
55519
|
+
}
|
|
55520
|
+
await electron$4.gitStash(t("Auto-stash before switching to :name", { name: localName }));
|
|
55521
|
+
await electron$4.gitCheckout(localName, create2);
|
|
55522
|
+
setInfo(t("Your changes were stashed. Restore them from the Stashes list below when you return."));
|
|
55523
|
+
return true;
|
|
55524
|
+
}
|
|
55525
|
+
}
|
|
54868
55526
|
async function checkout(name, remote2) {
|
|
54869
55527
|
try {
|
|
54870
55528
|
setError(null);
|
|
55529
|
+
setInfo(null);
|
|
54871
55530
|
const localName = remote2 ? name.replace(/^origin\//, "") : name;
|
|
54872
|
-
await
|
|
54873
|
-
|
|
54874
|
-
|
|
55531
|
+
if (await checkoutOrStash(localName, false)) {
|
|
55532
|
+
load2();
|
|
55533
|
+
onRefresh();
|
|
55534
|
+
}
|
|
54875
55535
|
} catch (e) {
|
|
54876
55536
|
setError(String(e));
|
|
54877
55537
|
}
|
|
@@ -54880,15 +55540,39 @@ function BranchesTab({ onRefresh }) {
|
|
|
54880
55540
|
if (!newBranch.trim()) return;
|
|
54881
55541
|
try {
|
|
54882
55542
|
setError(null);
|
|
54883
|
-
|
|
54884
|
-
|
|
54885
|
-
|
|
55543
|
+
setInfo(null);
|
|
55544
|
+
if (await checkoutOrStash(newBranch.trim(), true)) {
|
|
55545
|
+
setNewBranch("");
|
|
55546
|
+
setCreating(false);
|
|
55547
|
+
load2();
|
|
55548
|
+
onRefresh();
|
|
55549
|
+
}
|
|
55550
|
+
} catch (e) {
|
|
55551
|
+
setError(String(e));
|
|
55552
|
+
}
|
|
55553
|
+
}
|
|
55554
|
+
async function popStash(ref) {
|
|
55555
|
+
try {
|
|
55556
|
+
setError(null);
|
|
55557
|
+
setInfo(null);
|
|
55558
|
+
await electron$4.gitStashPop(ref);
|
|
54886
55559
|
load2();
|
|
54887
55560
|
onRefresh();
|
|
54888
55561
|
} catch (e) {
|
|
54889
55562
|
setError(String(e));
|
|
54890
55563
|
}
|
|
54891
55564
|
}
|
|
55565
|
+
async function dropStash(ref) {
|
|
55566
|
+
if (!confirm(t("Discard stashed changes (:ref)? This cannot be undone.", { ref }))) return;
|
|
55567
|
+
try {
|
|
55568
|
+
setError(null);
|
|
55569
|
+
setInfo(null);
|
|
55570
|
+
await electron$4.gitStashDrop(ref);
|
|
55571
|
+
load2();
|
|
55572
|
+
} catch (e) {
|
|
55573
|
+
setError(String(e));
|
|
55574
|
+
}
|
|
55575
|
+
}
|
|
54892
55576
|
async function addRemote() {
|
|
54893
55577
|
if (!remoteName.trim() || !remoteUrl.trim()) return;
|
|
54894
55578
|
try {
|
|
@@ -54947,7 +55631,8 @@ function BranchesTab({ onRefresh }) {
|
|
|
54947
55631
|
const remote = branches.filter((b) => b.remote && (!q || b.name.toLowerCase().includes(q)));
|
|
54948
55632
|
if (loading) return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-500 px-3 py-4", children: t("Loading…") });
|
|
54949
55633
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto", children: [
|
|
54950
|
-
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-red-400 px-3 py-1 truncate", children: error2 }),
|
|
55634
|
+
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-red-400 px-3 py-1 truncate", title: error2, children: error2 }),
|
|
55635
|
+
info && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-blue-300 px-3 py-1 bg-blue-900/20 border-b border-surface-800", children: info }),
|
|
54951
55636
|
loadError && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[11px] text-amber-400 px-3 py-1 truncate", title: loadError, children: [
|
|
54952
55637
|
t("Couldn't load git state:"),
|
|
54953
55638
|
" ",
|
|
@@ -55039,6 +55724,37 @@ function BranchesTab({ onRefresh }) {
|
|
|
55039
55724
|
))
|
|
55040
55725
|
] }),
|
|
55041
55726
|
q && local.length === 0 && remote.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "px-3 py-3 text-[11px] text-surface-500", children: t('No branches match ":filter".', { filter: filter2 }) }),
|
|
55727
|
+
stashes.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "border-t border-surface-800 mt-1", children: [
|
|
55728
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "px-3 py-1.5 text-[10px] uppercase tracking-widest text-surface-500 font-semibold", children: t("Stashes") }),
|
|
55729
|
+
stashes.map((s) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "group flex items-center gap-2 px-3 py-1.5 text-xs text-surface-300 hover:bg-surface-800/50", children: [
|
|
55730
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[10px] text-surface-500 shrink-0", children: s.ref }),
|
|
55731
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "truncate flex-1", title: s.branch ? t("on :branch: :message", { branch: s.branch, message: s.message }) : s.message, children: [
|
|
55732
|
+
s.message,
|
|
55733
|
+
s.branch && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-surface-600", children: [
|
|
55734
|
+
" ",
|
|
55735
|
+
t("(on :branch)", { branch: s.branch })
|
|
55736
|
+
] })
|
|
55737
|
+
] }),
|
|
55738
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55739
|
+
"button",
|
|
55740
|
+
{
|
|
55741
|
+
onClick: () => popStash(s.ref),
|
|
55742
|
+
className: "opacity-0 group-hover:opacity-100 text-[10px] text-blue-400 hover:text-blue-300 transition-all shrink-0",
|
|
55743
|
+
title: t("Restore these changes onto the current branch"),
|
|
55744
|
+
children: t("Pop")
|
|
55745
|
+
}
|
|
55746
|
+
),
|
|
55747
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55748
|
+
"button",
|
|
55749
|
+
{
|
|
55750
|
+
onClick: () => dropStash(s.ref),
|
|
55751
|
+
className: "opacity-0 group-hover:opacity-100 text-[10px] text-surface-500 hover:text-red-400 transition-all shrink-0",
|
|
55752
|
+
title: t("Discard this stash"),
|
|
55753
|
+
children: "✕"
|
|
55754
|
+
}
|
|
55755
|
+
)
|
|
55756
|
+
] }, s.ref))
|
|
55757
|
+
] }),
|
|
55042
55758
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "border-t border-surface-800 mt-1", children: [
|
|
55043
55759
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-1.5 flex items-center justify-between", children: [
|
|
55044
55760
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] uppercase tracking-widest text-surface-500 font-semibold", children: t("Remotes") }),
|
|
@@ -56599,7 +57315,7 @@ function AddBlockMenu({ onAdd: onAdd2 }) {
|
|
|
56599
57315
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-0 top-full mt-1 z-50 w-56 bg-surface-900 border border-surface-700 rounded-lg shadow-2xl max-h-[70vh] overflow-y-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsx(BlockPickerList, { onPick: (type) => {
|
|
56600
57316
|
onAdd2(type);
|
|
56601
57317
|
setOpen(false);
|
|
56602
|
-
} }) })
|
|
57318
|
+
}, includeEnd: true }) })
|
|
56603
57319
|
] })
|
|
56604
57320
|
] });
|
|
56605
57321
|
}
|
|
@@ -57837,6 +58553,43 @@ function App() {
|
|
|
57837
58553
|
});
|
|
57838
58554
|
return () => electron.offOpenFromGit();
|
|
57839
58555
|
}, [applyWorkspace]);
|
|
58556
|
+
reactExports.useEffect(() => {
|
|
58557
|
+
electron.onImportShare(async (token) => {
|
|
58558
|
+
try {
|
|
58559
|
+
const { type, name, payload } = await electron.cloudImportShare(token);
|
|
58560
|
+
let collection2;
|
|
58561
|
+
if (type === "request") {
|
|
58562
|
+
const r = payload;
|
|
58563
|
+
const reqId = r.id || crypto.randomUUID();
|
|
58564
|
+
const req = { ...r, id: reqId };
|
|
58565
|
+
collection2 = {
|
|
58566
|
+
version: "1.0",
|
|
58567
|
+
id: crypto.randomUUID(),
|
|
58568
|
+
name: name || req.name || "Shared request",
|
|
58569
|
+
rootFolder: { id: crypto.randomUUID(), name: "", folders: [], requestIds: [reqId] },
|
|
58570
|
+
requests: { [reqId]: req }
|
|
58571
|
+
};
|
|
58572
|
+
} else {
|
|
58573
|
+
collection2 = { ...payload, id: crypto.randomUUID() };
|
|
58574
|
+
}
|
|
58575
|
+
const store = useStore$1.getState();
|
|
58576
|
+
const id2 = store.addCollectionObject(collection2);
|
|
58577
|
+
try {
|
|
58578
|
+
const entry = useStore$1.getState().collections[id2];
|
|
58579
|
+
if (entry && useStore$1.getState().workspace) {
|
|
58580
|
+
await electron.saveCollection(entry.relPath, entry.data);
|
|
58581
|
+
await electron.saveWorkspace(useStore$1.getState().workspace);
|
|
58582
|
+
}
|
|
58583
|
+
} catch (persistErr) {
|
|
58584
|
+
console.error("Imported shared collection but could not save it yet:", persistErr);
|
|
58585
|
+
}
|
|
58586
|
+
setSidebarTab("collections");
|
|
58587
|
+
} catch (err) {
|
|
58588
|
+
console.error("Import from share link failed:", err);
|
|
58589
|
+
}
|
|
58590
|
+
});
|
|
58591
|
+
return () => electron.offImportShare();
|
|
58592
|
+
}, [setSidebarTab]);
|
|
57840
58593
|
reactExports.useEffect(() => {
|
|
57841
58594
|
electron.onMockHit(addMockHit);
|
|
57842
58595
|
return () => electron.offMockHit();
|
|
@@ -58005,7 +58758,7 @@ function App() {
|
|
|
58005
58758
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--wordmark-accent)" }, children: "Spector" }),
|
|
58006
58759
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-2 text-[10px] font-normal", style: { color: "var(--text-muted)" }, children: [
|
|
58007
58760
|
"v",
|
|
58008
|
-
"0.9.
|
|
58761
|
+
"0.9.2"
|
|
58009
58762
|
] }),
|
|
58010
58763
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mx-2 opacity-30", "aria-hidden": "true", children: "·" }),
|
|
58011
58764
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|