@testsmith/api-spector 0.1.0 → 0.1.1
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/index.js +117 -1
- package/out/main/runner.js +11 -2
- package/out/preload/index.js +20 -0
- package/out/renderer/assets/{index-CTaJ83Dp.js → index-B7b-1sj6.js} +930 -104
- package/out/renderer/assets/index-QI8AWMd3.css +2 -0
- package/out/renderer/index.html +2 -2
- package/package.json +2 -1
- package/out/renderer/assets/index-DE4e3iXO.css +0 -2
|
@@ -13983,7 +13983,7 @@ const useStore = create()(
|
|
|
13983
13983
|
})
|
|
13984
13984
|
}))
|
|
13985
13985
|
);
|
|
13986
|
-
const { electron: electron$
|
|
13986
|
+
const { electron: electron$m } = window;
|
|
13987
13987
|
function useAutoSave() {
|
|
13988
13988
|
const collections = useStore((s) => s.collections);
|
|
13989
13989
|
useStore((s) => s.environments);
|
|
@@ -13999,7 +13999,7 @@ function useAutoSave() {
|
|
|
13999
13999
|
for (const { relPath, data, dirty } of dirtyCollections) {
|
|
14000
14000
|
if (!dirty) continue;
|
|
14001
14001
|
try {
|
|
14002
|
-
await electron$
|
|
14002
|
+
await electron$m.saveCollection(relPath, data);
|
|
14003
14003
|
markCollectionClean(data.id);
|
|
14004
14004
|
} catch (e) {
|
|
14005
14005
|
console.error("Auto-save failed for", relPath, e);
|
|
@@ -14015,7 +14015,7 @@ function useAutoSave() {
|
|
|
14015
14015
|
if (wsTimerRef.current) clearTimeout(wsTimerRef.current);
|
|
14016
14016
|
wsTimerRef.current = setTimeout(async () => {
|
|
14017
14017
|
try {
|
|
14018
|
-
await electron$
|
|
14018
|
+
await electron$m.saveWorkspace(workspace);
|
|
14019
14019
|
} catch {
|
|
14020
14020
|
}
|
|
14021
14021
|
}, 300);
|
|
@@ -14024,7 +14024,7 @@ function useAutoSave() {
|
|
|
14024
14024
|
};
|
|
14025
14025
|
}, [workspace]);
|
|
14026
14026
|
}
|
|
14027
|
-
const { electron: electron$
|
|
14027
|
+
const { electron: electron$l } = window;
|
|
14028
14028
|
function useWorkspaceLoader() {
|
|
14029
14029
|
const loadCollection = useStore((s) => s.loadCollection);
|
|
14030
14030
|
const loadEnvironment = useStore((s) => s.loadEnvironment);
|
|
@@ -14043,28 +14043,28 @@ function useWorkspaceLoader() {
|
|
|
14043
14043
|
});
|
|
14044
14044
|
for (const colPath of ws2.collections) {
|
|
14045
14045
|
try {
|
|
14046
|
-
const col = await electron$
|
|
14046
|
+
const col = await electron$l.loadCollection(colPath);
|
|
14047
14047
|
loadCollection(colPath, col);
|
|
14048
14048
|
} catch {
|
|
14049
14049
|
}
|
|
14050
14050
|
}
|
|
14051
14051
|
for (const envPath of ws2.environments) {
|
|
14052
14052
|
try {
|
|
14053
|
-
const env = await electron$
|
|
14053
|
+
const env = await electron$l.loadEnvironment(envPath);
|
|
14054
14054
|
loadEnvironment(envPath, env);
|
|
14055
14055
|
} catch {
|
|
14056
14056
|
}
|
|
14057
14057
|
}
|
|
14058
14058
|
for (const relPath of ws2.mocks ?? []) {
|
|
14059
14059
|
try {
|
|
14060
|
-
const mockData = await electron$
|
|
14060
|
+
const mockData = await electron$l.loadMock(relPath);
|
|
14061
14061
|
loadMock(relPath, mockData);
|
|
14062
14062
|
} catch {
|
|
14063
14063
|
}
|
|
14064
14064
|
}
|
|
14065
14065
|
if (ws2.collections.length > 0) {
|
|
14066
14066
|
try {
|
|
14067
|
-
const firstCol = await electron$
|
|
14067
|
+
const firstCol = await electron$l.loadCollection(ws2.collections[0]);
|
|
14068
14068
|
setActiveCollection(firstCol.id);
|
|
14069
14069
|
} catch {
|
|
14070
14070
|
}
|
|
@@ -42246,7 +42246,7 @@ const autoCloseTags = /* @__PURE__ */ EditorView.inputHandler.of((view, from, to
|
|
|
42246
42246
|
]);
|
|
42247
42247
|
return true;
|
|
42248
42248
|
});
|
|
42249
|
-
const { electron: electron$
|
|
42249
|
+
const { electron: electron$k } = window;
|
|
42250
42250
|
function SoapEditor({ request, onChange }) {
|
|
42251
42251
|
const soap = request.body.soap ?? {
|
|
42252
42252
|
wsdlUrl: "",
|
|
@@ -42263,7 +42263,7 @@ function SoapEditor({ request, onChange }) {
|
|
|
42263
42263
|
setFetching(true);
|
|
42264
42264
|
setFetchError(null);
|
|
42265
42265
|
try {
|
|
42266
|
-
const result = await electron$
|
|
42266
|
+
const result = await electron$k.wsdlFetch(soap.wsdlUrl.trim());
|
|
42267
42267
|
setOperations(result.operations);
|
|
42268
42268
|
if (result.operations.length > 0) {
|
|
42269
42269
|
const first = result.operations[0];
|
|
@@ -42423,7 +42423,7 @@ function BodyTab({ request, onChange }) {
|
|
|
42423
42423
|
mode === "soap" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SoapEditor, { request, onChange }) })
|
|
42424
42424
|
] });
|
|
42425
42425
|
}
|
|
42426
|
-
const { electron: electron$
|
|
42426
|
+
const { electron: electron$j } = window;
|
|
42427
42427
|
const AUTH_TYPES = ["none", "bearer", "basic", "digest", "ntlm", "apikey", "oauth2"];
|
|
42428
42428
|
function AuthTab({ request, onChange }) {
|
|
42429
42429
|
const auth = request.auth;
|
|
@@ -42437,7 +42437,7 @@ function AuthTab({ request, onChange }) {
|
|
|
42437
42437
|
}
|
|
42438
42438
|
async function saveSecret(ref2) {
|
|
42439
42439
|
if (!secretValue || !ref2) return;
|
|
42440
|
-
await electron$
|
|
42440
|
+
await electron$j.setSecret(ref2, secretValue);
|
|
42441
42441
|
setSaved(true);
|
|
42442
42442
|
setSecretValue("");
|
|
42443
42443
|
setTimeout(() => setSaved(false), 2e3);
|
|
@@ -42448,14 +42448,14 @@ function AuthTab({ request, onChange }) {
|
|
|
42448
42448
|
try {
|
|
42449
42449
|
const vars = {};
|
|
42450
42450
|
if (auth.oauth2Flow === "authorization_code") {
|
|
42451
|
-
const result = await electron$
|
|
42451
|
+
const result = await electron$j.oauth2StartFlow(auth, vars);
|
|
42452
42452
|
setAuth({
|
|
42453
42453
|
oauth2CachedToken: result.accessToken,
|
|
42454
42454
|
oauth2TokenExpiry: result.expiresAt
|
|
42455
42455
|
});
|
|
42456
42456
|
if (result.refreshToken) setOauth2RT(result.refreshToken);
|
|
42457
42457
|
} else {
|
|
42458
|
-
const result = await electron$
|
|
42458
|
+
const result = await electron$j.oauth2StartFlow(auth, vars);
|
|
42459
42459
|
setAuth({
|
|
42460
42460
|
oauth2CachedToken: result.accessToken,
|
|
42461
42461
|
oauth2TokenExpiry: result.expiresAt
|
|
@@ -42473,7 +42473,7 @@ function AuthTab({ request, onChange }) {
|
|
|
42473
42473
|
setOauth2Status("fetching");
|
|
42474
42474
|
setOauth2Error("");
|
|
42475
42475
|
try {
|
|
42476
|
-
const result = await electron$
|
|
42476
|
+
const result = await electron$j.oauth2RefreshToken(auth, {}, oauth2RefreshToken);
|
|
42477
42477
|
setAuth({
|
|
42478
42478
|
oauth2CachedToken: result.accessToken,
|
|
42479
42479
|
oauth2TokenExpiry: result.expiresAt
|
|
@@ -49470,7 +49470,7 @@ function SchemaTab({ request, onChange }) {
|
|
|
49470
49470
|
] }) })
|
|
49471
49471
|
] });
|
|
49472
49472
|
}
|
|
49473
|
-
const { electron: electron$
|
|
49473
|
+
const { electron: electron$i } = window;
|
|
49474
49474
|
const EMPTY = { statusCode: 200, headers: [], bodySchema: "" };
|
|
49475
49475
|
function ContractTab({ request, onChange }) {
|
|
49476
49476
|
const activeTab = useStore((s) => s.tabs.find((t2) => t2.id === s.activeTabId));
|
|
@@ -49484,7 +49484,7 @@ function ContractTab({ request, onChange }) {
|
|
|
49484
49484
|
if (!lastResponse?.body) return;
|
|
49485
49485
|
setInferring(true);
|
|
49486
49486
|
try {
|
|
49487
|
-
const schema = await electron$
|
|
49487
|
+
const schema = await electron$i.inferContractSchema(lastResponse.body);
|
|
49488
49488
|
if (schema) update({ bodySchema: schema });
|
|
49489
49489
|
} finally {
|
|
49490
49490
|
setInferring(false);
|
|
@@ -49592,7 +49592,7 @@ function ContractTab({ request, onChange }) {
|
|
|
49592
49592
|
] })
|
|
49593
49593
|
] });
|
|
49594
49594
|
}
|
|
49595
|
-
const { electron: electron$
|
|
49595
|
+
const { electron: electron$h } = window;
|
|
49596
49596
|
function formatTime$1(ts) {
|
|
49597
49597
|
const d = new Date(ts);
|
|
49598
49598
|
const hh = String(d.getHours()).padStart(2, "0");
|
|
@@ -49612,14 +49612,14 @@ function WebSocketPanel({ request }) {
|
|
|
49612
49612
|
const [sendText, setSendText] = reactExports.useState("");
|
|
49613
49613
|
const logEndRef = reactExports.useRef(null);
|
|
49614
49614
|
reactExports.useEffect(() => {
|
|
49615
|
-
electron$
|
|
49615
|
+
electron$h.onWsMessage(({ requestId, message }) => {
|
|
49616
49616
|
addWsMessage(requestId, message);
|
|
49617
49617
|
});
|
|
49618
|
-
electron$
|
|
49618
|
+
electron$h.onWsStatus(({ requestId, status, error: error2 }) => {
|
|
49619
49619
|
setWsStatus(requestId, status, error2);
|
|
49620
49620
|
});
|
|
49621
49621
|
return () => {
|
|
49622
|
-
electron$
|
|
49622
|
+
electron$h.offWsEvents();
|
|
49623
49623
|
};
|
|
49624
49624
|
}, [addWsMessage, setWsStatus]);
|
|
49625
49625
|
reactExports.useEffect(() => {
|
|
@@ -49632,19 +49632,19 @@ function WebSocketPanel({ request }) {
|
|
|
49632
49632
|
if (h.enabled && h.key) headers[h.key] = h.value;
|
|
49633
49633
|
}
|
|
49634
49634
|
try {
|
|
49635
|
-
await electron$
|
|
49635
|
+
await electron$h.wsConnect(request.id, request.url, headers);
|
|
49636
49636
|
} catch (err) {
|
|
49637
49637
|
setWsStatus(request.id, "error", err instanceof Error ? err.message : String(err));
|
|
49638
49638
|
}
|
|
49639
49639
|
}
|
|
49640
49640
|
async function disconnect() {
|
|
49641
|
-
await electron$
|
|
49641
|
+
await electron$h.wsDisconnect(request.id);
|
|
49642
49642
|
}
|
|
49643
49643
|
async function sendMessage() {
|
|
49644
49644
|
const text = sendText.trim();
|
|
49645
49645
|
if (!text || !isConnected) return;
|
|
49646
49646
|
try {
|
|
49647
|
-
await electron$
|
|
49647
|
+
await electron$h.wsSend(request.id, text);
|
|
49648
49648
|
const msg = {
|
|
49649
49649
|
id: crypto.randomUUID(),
|
|
49650
49650
|
direction: "sent",
|
|
@@ -49747,7 +49747,7 @@ function WebSocketPanel({ request }) {
|
|
|
49747
49747
|
] })
|
|
49748
49748
|
] });
|
|
49749
49749
|
}
|
|
49750
|
-
const { electron: electron$
|
|
49750
|
+
const { electron: electron$g } = window;
|
|
49751
49751
|
const METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
49752
49752
|
const METHOD_COLORS = {
|
|
49753
49753
|
GET: "text-emerald-400",
|
|
@@ -49801,7 +49801,7 @@ function RequestBuilder({ request }) {
|
|
|
49801
49801
|
auth: mergedAuth,
|
|
49802
49802
|
headers: mergedHeaders
|
|
49803
49803
|
};
|
|
49804
|
-
const result = await electron$
|
|
49804
|
+
const result = await electron$g.sendRequest({
|
|
49805
49805
|
request: mergedRequest,
|
|
49806
49806
|
environment: activeEnv,
|
|
49807
49807
|
collectionVars,
|
|
@@ -50450,7 +50450,7 @@ function InteractiveBody({ body, contentType, onAssert }) {
|
|
|
50450
50450
|
treeContent
|
|
50451
50451
|
] });
|
|
50452
50452
|
}
|
|
50453
|
-
const { electron: electron$
|
|
50453
|
+
const { electron: electron$f } = window;
|
|
50454
50454
|
function prettyJson(raw) {
|
|
50455
50455
|
try {
|
|
50456
50456
|
return JSON.stringify(JSON.parse(raw), null, 2);
|
|
@@ -50536,14 +50536,14 @@ function SaveAsMockModal({ onClose }) {
|
|
|
50536
50536
|
const entry = state.mocks[serverId];
|
|
50537
50537
|
const updated = { ...entry.data, name: newServerName, port: Number(newServerPort), routes: [route] };
|
|
50538
50538
|
updateMock(serverId, updated);
|
|
50539
|
-
await electron$
|
|
50539
|
+
await electron$f.saveMock(entry.relPath, updated);
|
|
50540
50540
|
const ws2 = useStore.getState().workspace;
|
|
50541
|
-
if (ws2) await electron$
|
|
50541
|
+
if (ws2) await electron$f.saveWorkspace(ws2);
|
|
50542
50542
|
} else {
|
|
50543
50543
|
const entry = useStore.getState().mocks[serverId];
|
|
50544
50544
|
const updated = { ...entry.data, routes: [...entry.data.routes, route] };
|
|
50545
50545
|
updateMock(serverId, updated);
|
|
50546
|
-
await electron$
|
|
50546
|
+
await electron$f.saveMock(entry.relPath, updated);
|
|
50547
50547
|
}
|
|
50548
50548
|
onClose();
|
|
50549
50549
|
} finally {
|
|
@@ -50774,7 +50774,7 @@ function ResponseViewer() {
|
|
|
50774
50774
|
const [contractToast, setContractToast] = reactExports.useState(false);
|
|
50775
50775
|
async function saveAsContract() {
|
|
50776
50776
|
if (!response || !requestId || !activeTabId) return;
|
|
50777
|
-
const schema = response.body ? await electron$
|
|
50777
|
+
const schema = response.body ? await electron$f.inferContractSchema(response.body) : null;
|
|
50778
50778
|
const contentType2 = response.headers["content-type"];
|
|
50779
50779
|
const headers = contentType2 ? [{ key: "content-type", value: contentType2, required: true }] : [];
|
|
50780
50780
|
updateRequest(requestId, {
|
|
@@ -51017,7 +51017,7 @@ function ConsolePanel({ scriptResult }) {
|
|
|
51017
51017
|
i
|
|
51018
51018
|
)) });
|
|
51019
51019
|
}
|
|
51020
|
-
const { electron: electron$
|
|
51020
|
+
const { electron: electron$e } = window;
|
|
51021
51021
|
const TARGETS = [
|
|
51022
51022
|
{ id: "robot_framework", label: "Robot Framework", description: "Python RequestsLibrary keywords + test suite" },
|
|
51023
51023
|
{ id: "playwright_ts", label: "Playwright TS", description: "TypeScript page-object API classes + spec files" },
|
|
@@ -51048,7 +51048,7 @@ function GeneratorPanel() {
|
|
|
51048
51048
|
try {
|
|
51049
51049
|
const col = collections[selectedCollectionId]?.data;
|
|
51050
51050
|
const env = activeEnvironmentId ? environments[activeEnvironmentId]?.data ?? null : null;
|
|
51051
|
-
const generated = await electron$
|
|
51051
|
+
const generated = await electron$e.generateCode({ collection: col, environment: env, target });
|
|
51052
51052
|
setFiles(generated);
|
|
51053
51053
|
setSelectedFile(generated[0]?.path ?? null);
|
|
51054
51054
|
} catch (e) {
|
|
@@ -51060,7 +51060,7 @@ function GeneratorPanel() {
|
|
|
51060
51060
|
async function saveZip() {
|
|
51061
51061
|
if (files.length === 0) return;
|
|
51062
51062
|
const col = collections[selectedCollectionId]?.data;
|
|
51063
|
-
await electron$
|
|
51063
|
+
await electron$e.saveGeneratedFilesAsZip(files, col?.name ?? "api-tests", target);
|
|
51064
51064
|
}
|
|
51065
51065
|
const selectedContent = files.find((f) => f.path === selectedFile)?.content ?? "";
|
|
51066
51066
|
const activeTarget = TARGETS.find((t2) => t2.id === target);
|
|
@@ -51284,16 +51284,16 @@ function HistoryRow({
|
|
|
51284
51284
|
}
|
|
51285
51285
|
);
|
|
51286
51286
|
}
|
|
51287
|
-
const { electron: electron$
|
|
51287
|
+
const { electron: electron$d } = window;
|
|
51288
51288
|
function WelcomeScreen() {
|
|
51289
51289
|
const { applyWorkspace } = useWorkspaceLoader();
|
|
51290
51290
|
async function openWorkspace() {
|
|
51291
|
-
const result = await electron$
|
|
51291
|
+
const result = await electron$d.openWorkspace();
|
|
51292
51292
|
if (!result) return;
|
|
51293
51293
|
await applyWorkspace(result.workspace, result.workspacePath);
|
|
51294
51294
|
}
|
|
51295
51295
|
async function newWorkspace() {
|
|
51296
|
-
const result = await electron$
|
|
51296
|
+
const result = await electron$d.newWorkspace();
|
|
51297
51297
|
if (!result) return;
|
|
51298
51298
|
await applyWorkspace(result.workspace, result.workspacePath);
|
|
51299
51299
|
}
|
|
@@ -51327,7 +51327,7 @@ function WelcomeScreen() {
|
|
|
51327
51327
|
] })
|
|
51328
51328
|
] });
|
|
51329
51329
|
}
|
|
51330
|
-
const { electron: electron$
|
|
51330
|
+
const { electron: electron$c } = window;
|
|
51331
51331
|
const EXAMPLES = [
|
|
51332
51332
|
{
|
|
51333
51333
|
label: "macOS / Linux (~/.zshrc or ~/.bashrc)",
|
|
@@ -51351,7 +51351,7 @@ function MasterKeyModal({ onSuccess, onCancel }) {
|
|
|
51351
51351
|
setError("Password cannot be empty.");
|
|
51352
51352
|
return;
|
|
51353
51353
|
}
|
|
51354
|
-
await electron$
|
|
51354
|
+
await electron$c.setMasterKey(password);
|
|
51355
51355
|
onSuccess(password);
|
|
51356
51356
|
}
|
|
51357
51357
|
function copy(idx, text) {
|
|
@@ -51441,7 +51441,7 @@ function MasterKeyModal({ onSuccess, onCancel }) {
|
|
|
51441
51441
|
}
|
|
51442
51442
|
);
|
|
51443
51443
|
}
|
|
51444
|
-
const { electron: electron$
|
|
51444
|
+
const { electron: electron$b } = window;
|
|
51445
51445
|
async function shortHash(value) {
|
|
51446
51446
|
const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
|
|
51447
51447
|
return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 8);
|
|
@@ -51542,7 +51542,7 @@ function EnvironmentEditor({ onClose }) {
|
|
|
51542
51542
|
async function saveEncrypted(idx) {
|
|
51543
51543
|
const plaintext = secretInputs[idx] ?? "";
|
|
51544
51544
|
if (!plaintext) return;
|
|
51545
|
-
const { set: set2 } = await electron$
|
|
51545
|
+
const { set: set2 } = await electron$b.checkMasterKey();
|
|
51546
51546
|
if (!set2) {
|
|
51547
51547
|
setPendingEncryptIdx(idx);
|
|
51548
51548
|
return;
|
|
@@ -51579,9 +51579,9 @@ function EnvironmentEditor({ onClose }) {
|
|
|
51579
51579
|
} : state.workspace
|
|
51580
51580
|
}));
|
|
51581
51581
|
const ws2 = useStore.getState().workspace;
|
|
51582
|
-
if (ws2) await electron$
|
|
51582
|
+
if (ws2) await electron$b.saveWorkspace(ws2);
|
|
51583
51583
|
}
|
|
51584
|
-
await electron$
|
|
51584
|
+
await electron$b.saveEnvironment(newRelPath, env);
|
|
51585
51585
|
}
|
|
51586
51586
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
51587
51587
|
pendingEncryptIdx !== null && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -51865,7 +51865,7 @@ function EnvironmentEditor({ onClose }) {
|
|
|
51865
51865
|
)
|
|
51866
51866
|
] });
|
|
51867
51867
|
}
|
|
51868
|
-
const { electron: electron$
|
|
51868
|
+
const { electron: electron$a } = window;
|
|
51869
51869
|
function EnvironmentBar({ inline = false }) {
|
|
51870
51870
|
const environments = useStore((s) => s.environments);
|
|
51871
51871
|
const activeEnvironmentId = useStore((s) => s.activeEnvironmentId);
|
|
@@ -51879,7 +51879,7 @@ function EnvironmentBar({ inline = false }) {
|
|
|
51879
51879
|
if (id2) {
|
|
51880
51880
|
const hasSecrets = environments[id2]?.data.variables.some((v) => v.enabled && v.secret);
|
|
51881
51881
|
if (hasSecrets) {
|
|
51882
|
-
const { set: set2 } = await electron$
|
|
51882
|
+
const { set: set2 } = await electron$a.checkMasterKey();
|
|
51883
51883
|
if (!set2) {
|
|
51884
51884
|
setPendingEnvId(id2);
|
|
51885
51885
|
return;
|
|
@@ -51933,7 +51933,7 @@ function EnvironmentBar({ inline = false }) {
|
|
|
51933
51933
|
controls
|
|
51934
51934
|
] });
|
|
51935
51935
|
}
|
|
51936
|
-
const { electron: electron$
|
|
51936
|
+
const { electron: electron$9 } = window;
|
|
51937
51937
|
const DEFAULT_PII_PATTERNS = ["authorization", "password", "token", "secret", "api-key", "x-api-key"];
|
|
51938
51938
|
function WorkspaceSettingsModal({ onClose }) {
|
|
51939
51939
|
const workspace = useStore((s) => s.workspace);
|
|
@@ -51979,7 +51979,7 @@ function WorkspaceSettingsModal({ onClose }) {
|
|
|
51979
51979
|
settings.piiMaskPatterns = patterns;
|
|
51980
51980
|
updateWorkspaceSettings(settings);
|
|
51981
51981
|
const updated = useStore.getState().workspace;
|
|
51982
|
-
if (updated) await electron$
|
|
51982
|
+
if (updated) await electron$9.saveWorkspace(updated);
|
|
51983
51983
|
onClose();
|
|
51984
51984
|
}
|
|
51985
51985
|
const tabs = [
|
|
@@ -52177,7 +52177,7 @@ function WorkspaceSettingsModal({ onClose }) {
|
|
|
52177
52177
|
}
|
|
52178
52178
|
);
|
|
52179
52179
|
}
|
|
52180
|
-
const { electron: electron$
|
|
52180
|
+
const { electron: electron$8 } = window;
|
|
52181
52181
|
function DocsGeneratorModal({ onClose }) {
|
|
52182
52182
|
const collections = useStore((s) => s.collections);
|
|
52183
52183
|
const collectionList = Object.values(collections);
|
|
@@ -52206,9 +52206,9 @@ function DocsGeneratorModal({ onClose }) {
|
|
|
52206
52206
|
setGenerating(true);
|
|
52207
52207
|
setError(null);
|
|
52208
52208
|
try {
|
|
52209
|
-
const content2 = await electron$
|
|
52209
|
+
const content2 = await electron$8.generateDocs(buildPayload());
|
|
52210
52210
|
const filename = format2 === "html" ? "api-docs.html" : "api-docs.md";
|
|
52211
|
-
await electron$
|
|
52211
|
+
await electron$8.saveResults(content2, filename);
|
|
52212
52212
|
} catch (err) {
|
|
52213
52213
|
setError(err instanceof Error ? err.message : String(err));
|
|
52214
52214
|
} finally {
|
|
@@ -52219,7 +52219,7 @@ function DocsGeneratorModal({ onClose }) {
|
|
|
52219
52219
|
setGenerating(true);
|
|
52220
52220
|
setError(null);
|
|
52221
52221
|
try {
|
|
52222
|
-
const content2 = await electron$
|
|
52222
|
+
const content2 = await electron$8.generateDocs(buildPayload());
|
|
52223
52223
|
setPreview(content2);
|
|
52224
52224
|
} catch (err) {
|
|
52225
52225
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -52335,7 +52335,7 @@ function DocsGeneratorModal({ onClose }) {
|
|
|
52335
52335
|
] })
|
|
52336
52336
|
] }) });
|
|
52337
52337
|
}
|
|
52338
|
-
const { electron: electron$
|
|
52338
|
+
const { electron: electron$7 } = window;
|
|
52339
52339
|
const OPTIONS = [
|
|
52340
52340
|
{ id: "postman", label: "Postman", description: "Collection v2.1 JSON" },
|
|
52341
52341
|
{ id: "openapi", label: "OpenAPI", description: "JSON or YAML (v3.x)", supportsUrl: true },
|
|
@@ -52353,10 +52353,10 @@ function ImportModal({ onImport, onClose }) {
|
|
|
52353
52353
|
setError(null);
|
|
52354
52354
|
try {
|
|
52355
52355
|
let col = null;
|
|
52356
|
-
if (opt.id === "postman") col = await electron$
|
|
52357
|
-
if (opt.id === "openapi") col = await electron$
|
|
52358
|
-
if (opt.id === "insomnia") col = await electron$
|
|
52359
|
-
if (opt.id === "bruno") col = await electron$
|
|
52356
|
+
if (opt.id === "postman") col = await electron$7.importPostman();
|
|
52357
|
+
if (opt.id === "openapi") col = await electron$7.importOpenApi();
|
|
52358
|
+
if (opt.id === "insomnia") col = await electron$7.importInsomnia();
|
|
52359
|
+
if (opt.id === "bruno") col = await electron$7.importBruno();
|
|
52360
52360
|
onImport(col);
|
|
52361
52361
|
onClose();
|
|
52362
52362
|
} catch (err) {
|
|
@@ -52371,7 +52371,7 @@ function ImportModal({ onImport, onClose }) {
|
|
|
52371
52371
|
setLoading(true);
|
|
52372
52372
|
setError(null);
|
|
52373
52373
|
try {
|
|
52374
|
-
const col = await electron$
|
|
52374
|
+
const col = await electron$7.importOpenApiFromUrl(trimmed);
|
|
52375
52375
|
onImport(col);
|
|
52376
52376
|
onClose();
|
|
52377
52377
|
} catch (err) {
|
|
@@ -52466,7 +52466,7 @@ function ImportModal({ onImport, onClose }) {
|
|
|
52466
52466
|
}
|
|
52467
52467
|
) });
|
|
52468
52468
|
}
|
|
52469
|
-
const { electron: electron$
|
|
52469
|
+
const { electron: electron$6 } = window;
|
|
52470
52470
|
const ZOOM_STEPS = [0.75, 0.9, 1, 1.1, 1.25, 1.5];
|
|
52471
52471
|
function PreferencesPopover() {
|
|
52472
52472
|
const theme2 = useStore((s) => s.theme);
|
|
@@ -52572,13 +52572,13 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
52572
52572
|
try {
|
|
52573
52573
|
for (const { relPath, data, dirty } of Object.values(collections)) {
|
|
52574
52574
|
if (!dirty) continue;
|
|
52575
|
-
await electron$
|
|
52575
|
+
await electron$6.saveCollection(relPath, data);
|
|
52576
52576
|
markCollectionClean(data.id);
|
|
52577
52577
|
}
|
|
52578
52578
|
for (const { relPath, data } of Object.values(environments)) {
|
|
52579
|
-
await electron$
|
|
52579
|
+
await electron$6.saveEnvironment(relPath, data);
|
|
52580
52580
|
}
|
|
52581
|
-
if (workspace) await electron$
|
|
52581
|
+
if (workspace) await electron$6.saveWorkspace(workspace);
|
|
52582
52582
|
} finally {
|
|
52583
52583
|
setSaving(false);
|
|
52584
52584
|
}
|
|
@@ -52586,14 +52586,14 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
52586
52586
|
async function afterImport(col) {
|
|
52587
52587
|
if (!col) return;
|
|
52588
52588
|
const relPath = colRelPath(col.name, col.id);
|
|
52589
|
-
await electron$
|
|
52589
|
+
await electron$6.saveCollection(relPath, col);
|
|
52590
52590
|
loadCollection(relPath, col);
|
|
52591
52591
|
setActiveCollection(col.id);
|
|
52592
52592
|
const ws2 = useStore.getState().workspace;
|
|
52593
52593
|
if (ws2 && !ws2.collections.includes(relPath)) {
|
|
52594
52594
|
const updated = { ...ws2, collections: [...ws2.collections, relPath] };
|
|
52595
52595
|
useStore.setState({ workspace: updated });
|
|
52596
|
-
await electron$
|
|
52596
|
+
await electron$6.saveWorkspace(updated);
|
|
52597
52597
|
}
|
|
52598
52598
|
}
|
|
52599
52599
|
if (!workspace) return null;
|
|
@@ -52659,7 +52659,7 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
52659
52659
|
"button",
|
|
52660
52660
|
{
|
|
52661
52661
|
onClick: async () => {
|
|
52662
|
-
const result = await electron$
|
|
52662
|
+
const result = await electron$6.openWorkspace();
|
|
52663
52663
|
if (result) await applyWorkspace(result.workspace, result.workspacePath);
|
|
52664
52664
|
},
|
|
52665
52665
|
className: "px-2.5 py-1 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
@@ -52671,7 +52671,7 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
52671
52671
|
"button",
|
|
52672
52672
|
{
|
|
52673
52673
|
onClick: async () => {
|
|
52674
|
-
const result = await electron$
|
|
52674
|
+
const result = await electron$6.newWorkspace();
|
|
52675
52675
|
if (result) await applyWorkspace(result.workspace, result.workspacePath);
|
|
52676
52676
|
},
|
|
52677
52677
|
className: "px-2.5 py-1 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
@@ -52683,7 +52683,7 @@ function Toolbar({ onOpenDocs: _onOpenDocs }) {
|
|
|
52683
52683
|
"button",
|
|
52684
52684
|
{
|
|
52685
52685
|
onClick: async () => {
|
|
52686
|
-
await electron$
|
|
52686
|
+
await electron$6.closeWorkspace();
|
|
52687
52687
|
closeWorkspace();
|
|
52688
52688
|
},
|
|
52689
52689
|
className: "px-2.5 py-1 text-xs bg-surface-800 hover:bg-surface-700 rounded transition-colors",
|
|
@@ -53080,7 +53080,7 @@ api-tests:
|
|
|
53080
53080
|
function EmptyState({ message }) {
|
|
53081
53081
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center h-24 text-surface-400 text-xs", children: message });
|
|
53082
53082
|
}
|
|
53083
|
-
const { electron: electron$
|
|
53083
|
+
const { electron: electron$5 } = window;
|
|
53084
53084
|
function collectRequests(collectionId, folderId, filterTags) {
|
|
53085
53085
|
const state = useStore.getState();
|
|
53086
53086
|
const col = state.collections[collectionId]?.data;
|
|
@@ -53176,13 +53176,13 @@ function RunnerModal() {
|
|
|
53176
53176
|
setSummary(null);
|
|
53177
53177
|
setRunnerRunning(true);
|
|
53178
53178
|
progressIdxRef.current = 0;
|
|
53179
|
-
electron$
|
|
53179
|
+
electron$5.onRunProgress((result) => {
|
|
53180
53180
|
const idx = progressIdxRef.current;
|
|
53181
53181
|
patchRunnerResult(idx, result);
|
|
53182
53182
|
if (result.status !== "running") progressIdxRef.current++;
|
|
53183
53183
|
});
|
|
53184
53184
|
try {
|
|
53185
|
-
const s = await electron$
|
|
53185
|
+
const s = await electron$5.runCollection({
|
|
53186
53186
|
items: items2,
|
|
53187
53187
|
environment: env,
|
|
53188
53188
|
globals,
|
|
@@ -53193,7 +53193,7 @@ function RunnerModal() {
|
|
|
53193
53193
|
});
|
|
53194
53194
|
setSummary(s);
|
|
53195
53195
|
} finally {
|
|
53196
|
-
electron$
|
|
53196
|
+
electron$5.offRunProgress();
|
|
53197
53197
|
setRunnerRunning(false);
|
|
53198
53198
|
}
|
|
53199
53199
|
}, [collectionId, folderId, filterTags, selectedEnvId, environments, globals, colEntry, requestDelay, workspaceSettings, setRunnerResults, patchRunnerResult, setRunnerRunning]);
|
|
@@ -53406,7 +53406,7 @@ function RunnerModal() {
|
|
|
53406
53406
|
};
|
|
53407
53407
|
const content2 = exportFormat === "junit" ? buildJUnitReport(runnerResults, summary, meta2) : exportFormat === "html" ? buildHtmlReport(runnerResults, summary, meta2) : buildJsonReport(runnerResults, summary, meta2);
|
|
53408
53408
|
const ext = exportFormat === "junit" ? "xml" : exportFormat === "html" ? "html" : "json";
|
|
53409
|
-
electron$
|
|
53409
|
+
electron$5.saveResults(content2, `spector-results.${ext}`);
|
|
53410
53410
|
},
|
|
53411
53411
|
className: "px-2.5 py-0.5 bg-surface-800 hover:bg-surface-700 rounded transition-colors text-[11px] whitespace-nowrap",
|
|
53412
53412
|
children: "Export results"
|
|
@@ -53624,7 +53624,7 @@ function CollectionPanel() {
|
|
|
53624
53624
|
] })
|
|
53625
53625
|
] });
|
|
53626
53626
|
}
|
|
53627
|
-
const { electron: electron$
|
|
53627
|
+
const { electron: electron$4 } = window;
|
|
53628
53628
|
function MockPanel() {
|
|
53629
53629
|
const mocks = useStore((s) => s.mocks);
|
|
53630
53630
|
const activeMockId = useStore((s) => s.activeMockId);
|
|
@@ -53636,12 +53636,12 @@ function MockPanel() {
|
|
|
53636
53636
|
async function handleAddMock() {
|
|
53637
53637
|
addMock();
|
|
53638
53638
|
const ws2 = useStore.getState().workspace;
|
|
53639
|
-
if (ws2) await electron$
|
|
53639
|
+
if (ws2) await electron$4.saveWorkspace(ws2);
|
|
53640
53640
|
const state = useStore.getState();
|
|
53641
53641
|
const newId = state.activeMockId;
|
|
53642
53642
|
if (newId) {
|
|
53643
53643
|
const entry = state.mocks[newId];
|
|
53644
|
-
await electron$
|
|
53644
|
+
await electron$4.saveMock(entry.relPath, entry.data);
|
|
53645
53645
|
setActiveMock(newId);
|
|
53646
53646
|
}
|
|
53647
53647
|
}
|
|
@@ -53649,10 +53649,10 @@ function MockPanel() {
|
|
|
53649
53649
|
e.stopPropagation();
|
|
53650
53650
|
const entry = useStore.getState().mocks[mockId];
|
|
53651
53651
|
if (!entry) return;
|
|
53652
|
-
if (entry.running) await electron$
|
|
53652
|
+
if (entry.running) await electron$4.mockStop(mockId);
|
|
53653
53653
|
deleteMock(mockId);
|
|
53654
53654
|
const ws2 = useStore.getState().workspace;
|
|
53655
|
-
if (ws2) await electron$
|
|
53655
|
+
if (ws2) await electron$4.saveWorkspace(ws2);
|
|
53656
53656
|
}
|
|
53657
53657
|
async function toggleRunning(e, mockId) {
|
|
53658
53658
|
e.stopPropagation();
|
|
@@ -53660,12 +53660,12 @@ function MockPanel() {
|
|
|
53660
53660
|
if (!entry) return;
|
|
53661
53661
|
try {
|
|
53662
53662
|
if (entry.running) {
|
|
53663
|
-
await electron$
|
|
53663
|
+
await electron$4.mockStop(mockId);
|
|
53664
53664
|
setRunning(mockId, false);
|
|
53665
53665
|
} else {
|
|
53666
53666
|
const latest2 = useStore.getState().mocks[mockId].data;
|
|
53667
|
-
await electron$
|
|
53668
|
-
await electron$
|
|
53667
|
+
await electron$4.saveMock(entry.relPath, latest2);
|
|
53668
|
+
await electron$4.mockStart(latest2);
|
|
53669
53669
|
setRunning(mockId, true);
|
|
53670
53670
|
}
|
|
53671
53671
|
} catch {
|
|
@@ -53741,7 +53741,7 @@ function MockPanel() {
|
|
|
53741
53741
|
}) })
|
|
53742
53742
|
] });
|
|
53743
53743
|
}
|
|
53744
|
-
const { electron: electron$
|
|
53744
|
+
const { electron: electron$3 } = window;
|
|
53745
53745
|
const METHODS_PLUS_ANY = ["ANY", "GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
53746
53746
|
function RouteRow({
|
|
53747
53747
|
route,
|
|
@@ -54143,20 +54143,20 @@ function MockDetailPanel({ mockId }) {
|
|
|
54143
54143
|
const routes = mock.routes ?? [];
|
|
54144
54144
|
async function save(updated) {
|
|
54145
54145
|
updateMock(mock.id, updated);
|
|
54146
|
-
await electron$
|
|
54147
|
-
if (running) await electron$
|
|
54148
|
-
if (workspace) await electron$
|
|
54146
|
+
await electron$3.saveMock(entry.relPath, updated);
|
|
54147
|
+
if (running) await electron$3.mockUpdateRoutes(mock.id, updated.routes ?? []);
|
|
54148
|
+
if (workspace) await electron$3.saveWorkspace(workspace);
|
|
54149
54149
|
}
|
|
54150
54150
|
async function toggleRunning() {
|
|
54151
54151
|
setError(null);
|
|
54152
54152
|
try {
|
|
54153
54153
|
if (running) {
|
|
54154
|
-
await electron$
|
|
54154
|
+
await electron$3.mockStop(mock.id);
|
|
54155
54155
|
setRunning(mock.id, false);
|
|
54156
54156
|
} else {
|
|
54157
54157
|
const latest2 = useStore.getState().mocks[mock.id].data;
|
|
54158
|
-
await electron$
|
|
54159
|
-
await electron$
|
|
54158
|
+
await electron$3.saveMock(entry.relPath, latest2);
|
|
54159
|
+
await electron$3.mockStart(latest2);
|
|
54160
54160
|
setRunning(mock.id, true);
|
|
54161
54161
|
}
|
|
54162
54162
|
} catch (e) {
|
|
@@ -54269,7 +54269,7 @@ function MockDetailPanel({ mockId }) {
|
|
|
54269
54269
|
"button",
|
|
54270
54270
|
{
|
|
54271
54271
|
onClick: () => {
|
|
54272
|
-
if (running) electron$
|
|
54272
|
+
if (running) electron$3.mockStop(mock.id);
|
|
54273
54273
|
deleteMock(mock.id);
|
|
54274
54274
|
setActive2(null);
|
|
54275
54275
|
},
|
|
@@ -54336,7 +54336,7 @@ function MockDetailPanel({ mockId }) {
|
|
|
54336
54336
|
] })
|
|
54337
54337
|
] });
|
|
54338
54338
|
}
|
|
54339
|
-
const { electron: electron$
|
|
54339
|
+
const { electron: electron$2 } = window;
|
|
54340
54340
|
function ContractPanel() {
|
|
54341
54341
|
const collections = useStore((s) => s.collections);
|
|
54342
54342
|
const environments = useStore((s) => s.environments);
|
|
@@ -54367,7 +54367,7 @@ function ContractPanel() {
|
|
|
54367
54367
|
setReport(null);
|
|
54368
54368
|
try {
|
|
54369
54369
|
const requests = mode === "provider" ? allRequests : contractRequests;
|
|
54370
|
-
const result = await electron$
|
|
54370
|
+
const result = await electron$2.runContracts({
|
|
54371
54371
|
mode,
|
|
54372
54372
|
requests,
|
|
54373
54373
|
envVars,
|
|
@@ -54565,6 +54565,812 @@ function ContractResultsPanel() {
|
|
|
54565
54565
|
})() })
|
|
54566
54566
|
] });
|
|
54567
54567
|
}
|
|
54568
|
+
const { electron: electron$1 } = window;
|
|
54569
|
+
function useToast() {
|
|
54570
|
+
const [toast, setToast] = reactExports.useState(null);
|
|
54571
|
+
const timer = reactExports.useRef(null);
|
|
54572
|
+
function show(msg, ok) {
|
|
54573
|
+
if (timer.current) clearTimeout(timer.current);
|
|
54574
|
+
setToast({ msg, ok });
|
|
54575
|
+
timer.current = setTimeout(() => setToast(null), 3e3);
|
|
54576
|
+
}
|
|
54577
|
+
return { toast, show };
|
|
54578
|
+
}
|
|
54579
|
+
function Toast({ toast }) {
|
|
54580
|
+
if (!toast) return null;
|
|
54581
|
+
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 });
|
|
54582
|
+
}
|
|
54583
|
+
function StatusBadge({ status }) {
|
|
54584
|
+
const map = {
|
|
54585
|
+
modified: { label: "M", color: "text-amber-400" },
|
|
54586
|
+
added: { label: "A", color: "text-emerald-400" },
|
|
54587
|
+
deleted: { label: "D", color: "text-red-400" },
|
|
54588
|
+
renamed: { label: "R", color: "text-blue-400" },
|
|
54589
|
+
untracked: { label: "?", color: "text-surface-500" }
|
|
54590
|
+
};
|
|
54591
|
+
const { label, color } = map[status] ?? { label: "?", color: "text-surface-500" };
|
|
54592
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `font-mono text-[11px] font-bold w-4 shrink-0 ${color}`, children: label });
|
|
54593
|
+
}
|
|
54594
|
+
function DiffViewer({ diff }) {
|
|
54595
|
+
if (!diff) return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-500 p-3", children: "No changes." });
|
|
54596
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-[11px] font-mono overflow-auto p-3 leading-relaxed", children: diff.split("\n").map((line, i) => {
|
|
54597
|
+
const cls = line.startsWith("+") && !line.startsWith("+++") ? "text-emerald-400" : line.startsWith("-") && !line.startsWith("---") ? "text-red-400" : line.startsWith("@@") ? "text-blue-400" : "text-surface-400";
|
|
54598
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cls, children: line || " " }, i);
|
|
54599
|
+
}) });
|
|
54600
|
+
}
|
|
54601
|
+
function ChangesTab({ status, onRefresh }) {
|
|
54602
|
+
const [message, setMessage] = reactExports.useState("");
|
|
54603
|
+
const [diffFile, setDiffFile] = reactExports.useState(null);
|
|
54604
|
+
const [diff, setDiff] = reactExports.useState("");
|
|
54605
|
+
const [diffStaged, setDiffStaged] = reactExports.useState(false);
|
|
54606
|
+
const [error2, setError] = reactExports.useState(null);
|
|
54607
|
+
const [pushing, setPushing] = reactExports.useState(false);
|
|
54608
|
+
const [pulling, setPulling] = reactExports.useState(false);
|
|
54609
|
+
const { toast, show: showToast } = useToast();
|
|
54610
|
+
async function showDiff(file, staged) {
|
|
54611
|
+
setDiffFile(file.path);
|
|
54612
|
+
setDiffStaged(staged);
|
|
54613
|
+
try {
|
|
54614
|
+
const d = staged ? await electron$1.gitDiffStaged(file.path) : await electron$1.gitDiff(file.path);
|
|
54615
|
+
setDiff(d);
|
|
54616
|
+
} catch {
|
|
54617
|
+
setDiff("");
|
|
54618
|
+
}
|
|
54619
|
+
}
|
|
54620
|
+
async function stage(paths) {
|
|
54621
|
+
try {
|
|
54622
|
+
await electron$1.gitStage(paths);
|
|
54623
|
+
onRefresh();
|
|
54624
|
+
} catch (e) {
|
|
54625
|
+
setError(String(e));
|
|
54626
|
+
}
|
|
54627
|
+
}
|
|
54628
|
+
async function unstage(paths) {
|
|
54629
|
+
try {
|
|
54630
|
+
await electron$1.gitUnstage(paths);
|
|
54631
|
+
onRefresh();
|
|
54632
|
+
} catch (e) {
|
|
54633
|
+
setError(String(e));
|
|
54634
|
+
}
|
|
54635
|
+
}
|
|
54636
|
+
async function stageAll() {
|
|
54637
|
+
try {
|
|
54638
|
+
await electron$1.gitStageAll();
|
|
54639
|
+
onRefresh();
|
|
54640
|
+
} catch (e) {
|
|
54641
|
+
setError(String(e));
|
|
54642
|
+
}
|
|
54643
|
+
}
|
|
54644
|
+
async function commit() {
|
|
54645
|
+
if (!message.trim()) return;
|
|
54646
|
+
try {
|
|
54647
|
+
setError(null);
|
|
54648
|
+
await electron$1.gitCommit(message.trim());
|
|
54649
|
+
setMessage("");
|
|
54650
|
+
onRefresh();
|
|
54651
|
+
} catch (e) {
|
|
54652
|
+
setError(String(e));
|
|
54653
|
+
}
|
|
54654
|
+
}
|
|
54655
|
+
async function pull() {
|
|
54656
|
+
setPulling(true);
|
|
54657
|
+
try {
|
|
54658
|
+
await electron$1.gitPull();
|
|
54659
|
+
showToast("Pull successful", true);
|
|
54660
|
+
onRefresh();
|
|
54661
|
+
} catch (e) {
|
|
54662
|
+
showToast(String(e), false);
|
|
54663
|
+
} finally {
|
|
54664
|
+
setPulling(false);
|
|
54665
|
+
}
|
|
54666
|
+
}
|
|
54667
|
+
async function push2() {
|
|
54668
|
+
setPushing(true);
|
|
54669
|
+
try {
|
|
54670
|
+
await electron$1.gitPush(!status.remote);
|
|
54671
|
+
showToast("Push successful", true);
|
|
54672
|
+
onRefresh();
|
|
54673
|
+
} catch (e) {
|
|
54674
|
+
showToast(String(e), false);
|
|
54675
|
+
} finally {
|
|
54676
|
+
setPushing(false);
|
|
54677
|
+
}
|
|
54678
|
+
}
|
|
54679
|
+
const allUnstaged = [...status.unstaged, ...status.untracked];
|
|
54680
|
+
const hasStaged = status.staged.length > 0;
|
|
54681
|
+
const needsPush = status.ahead > 0;
|
|
54682
|
+
const needsPull = status.behind > 0;
|
|
54683
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col flex-1 min-h-0", children: [
|
|
54684
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-2 border-b border-surface-800 flex items-center gap-2 flex-shrink-0", children: [
|
|
54685
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[11px] font-mono text-blue-300 truncate flex-1", children: [
|
|
54686
|
+
"⎇ ",
|
|
54687
|
+
status.branch || "no branch"
|
|
54688
|
+
] }),
|
|
54689
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54690
|
+
"button",
|
|
54691
|
+
{
|
|
54692
|
+
onClick: pull,
|
|
54693
|
+
disabled: pulling,
|
|
54694
|
+
title: needsPull ? `Pull (${status.behind} behind)` : "Pull",
|
|
54695
|
+
className: `flex items-center gap-0.5 text-xs px-1.5 py-0.5 rounded transition-colors disabled:opacity-40 ${needsPull ? "text-amber-300 bg-amber-900/30 hover:bg-amber-900/50" : "text-surface-400 hover:text-white"}`,
|
|
54696
|
+
children: [
|
|
54697
|
+
"↓",
|
|
54698
|
+
needsPull ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px]", children: status.behind }) : null
|
|
54699
|
+
]
|
|
54700
|
+
}
|
|
54701
|
+
),
|
|
54702
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54703
|
+
"button",
|
|
54704
|
+
{
|
|
54705
|
+
onClick: push2,
|
|
54706
|
+
disabled: pushing,
|
|
54707
|
+
title: needsPush ? `Push (${status.ahead} unpushed)` : status.remote ? "Push" : "Push & set upstream",
|
|
54708
|
+
className: `flex items-center gap-0.5 text-xs px-1.5 py-0.5 rounded transition-colors disabled:opacity-40 ${needsPush ? "text-blue-300 bg-blue-900/30 hover:bg-blue-900/50" : "text-surface-400 hover:text-white"}`,
|
|
54709
|
+
children: [
|
|
54710
|
+
"↑",
|
|
54711
|
+
needsPush ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px]", children: status.ahead }) : null
|
|
54712
|
+
]
|
|
54713
|
+
}
|
|
54714
|
+
)
|
|
54715
|
+
] }),
|
|
54716
|
+
status.remote && (needsPush ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mx-3 mt-2 px-2 py-1.5 rounded text-[11px] bg-blue-900/20 text-blue-300 border border-blue-800/40 flex items-center justify-between flex-shrink-0", children: [
|
|
54717
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
54718
|
+
status.ahead,
|
|
54719
|
+
" commit",
|
|
54720
|
+
status.ahead !== 1 ? "s" : "",
|
|
54721
|
+
" to push"
|
|
54722
|
+
] }),
|
|
54723
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54724
|
+
"button",
|
|
54725
|
+
{
|
|
54726
|
+
onClick: push2,
|
|
54727
|
+
disabled: pushing,
|
|
54728
|
+
className: "text-blue-400 hover:text-blue-200 font-medium disabled:opacity-40",
|
|
54729
|
+
children: "Push ↑"
|
|
54730
|
+
}
|
|
54731
|
+
)
|
|
54732
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-3 mt-2 px-2 py-1 rounded text-[11px] text-surface-600 border border-surface-800 flex-shrink-0", children: "✓ Nothing to push" })),
|
|
54733
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Toast, { toast }),
|
|
54734
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-h-0 overflow-y-auto", children: [
|
|
54735
|
+
hasStaged && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { children: [
|
|
54736
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-1.5 flex items-center justify-between", children: [
|
|
54737
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] uppercase tracking-widest text-surface-500 font-semibold", children: [
|
|
54738
|
+
"Staged (",
|
|
54739
|
+
status.staged.length,
|
|
54740
|
+
")"
|
|
54741
|
+
] }),
|
|
54742
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54743
|
+
"button",
|
|
54744
|
+
{
|
|
54745
|
+
onClick: () => unstage(status.staged.map((f) => f.path)),
|
|
54746
|
+
className: "text-[10px] text-surface-500 hover:text-white transition-colors",
|
|
54747
|
+
children: "Unstage all"
|
|
54748
|
+
}
|
|
54749
|
+
)
|
|
54750
|
+
] }),
|
|
54751
|
+
status.staged.map((f) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54752
|
+
"div",
|
|
54753
|
+
{
|
|
54754
|
+
className: `flex items-center gap-2 px-3 py-1 hover:bg-surface-800/50 cursor-pointer group text-xs ${diffFile === f.path && diffStaged ? "bg-surface-800" : ""}`,
|
|
54755
|
+
onClick: () => showDiff(f, true),
|
|
54756
|
+
children: [
|
|
54757
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(StatusBadge, { status: f.status }),
|
|
54758
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate text-surface-200", children: f.path }),
|
|
54759
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54760
|
+
"button",
|
|
54761
|
+
{
|
|
54762
|
+
onClick: (e) => {
|
|
54763
|
+
e.stopPropagation();
|
|
54764
|
+
unstage([f.path]);
|
|
54765
|
+
},
|
|
54766
|
+
className: "opacity-0 group-hover:opacity-100 text-surface-500 hover:text-amber-400 transition-all text-[10px]",
|
|
54767
|
+
title: "Unstage",
|
|
54768
|
+
children: "−"
|
|
54769
|
+
}
|
|
54770
|
+
)
|
|
54771
|
+
]
|
|
54772
|
+
},
|
|
54773
|
+
f.path
|
|
54774
|
+
))
|
|
54775
|
+
] }),
|
|
54776
|
+
allUnstaged.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { children: [
|
|
54777
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-1.5 flex items-center justify-between", children: [
|
|
54778
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] uppercase tracking-widest text-surface-500 font-semibold", children: [
|
|
54779
|
+
"Changes (",
|
|
54780
|
+
allUnstaged.length,
|
|
54781
|
+
")"
|
|
54782
|
+
] }),
|
|
54783
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54784
|
+
"button",
|
|
54785
|
+
{
|
|
54786
|
+
onClick: stageAll,
|
|
54787
|
+
className: "text-[10px] text-surface-500 hover:text-white transition-colors",
|
|
54788
|
+
children: "Stage all"
|
|
54789
|
+
}
|
|
54790
|
+
)
|
|
54791
|
+
] }),
|
|
54792
|
+
allUnstaged.map((f) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54793
|
+
"div",
|
|
54794
|
+
{
|
|
54795
|
+
className: `flex items-center gap-2 px-3 py-1 hover:bg-surface-800/50 cursor-pointer group text-xs ${diffFile === f.path && !diffStaged ? "bg-surface-800" : ""}`,
|
|
54796
|
+
onClick: () => showDiff(f, false),
|
|
54797
|
+
children: [
|
|
54798
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(StatusBadge, { status: f.status }),
|
|
54799
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate text-surface-200", children: f.path }),
|
|
54800
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54801
|
+
"button",
|
|
54802
|
+
{
|
|
54803
|
+
onClick: (e) => {
|
|
54804
|
+
e.stopPropagation();
|
|
54805
|
+
stage([f.path]);
|
|
54806
|
+
},
|
|
54807
|
+
className: "opacity-0 group-hover:opacity-100 text-surface-500 hover:text-emerald-400 transition-all text-[10px]",
|
|
54808
|
+
title: "Stage",
|
|
54809
|
+
children: "+"
|
|
54810
|
+
}
|
|
54811
|
+
)
|
|
54812
|
+
]
|
|
54813
|
+
},
|
|
54814
|
+
f.path
|
|
54815
|
+
))
|
|
54816
|
+
] }),
|
|
54817
|
+
status.staged.length === 0 && allUnstaged.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-500 px-3 py-4", children: "Working tree clean." })
|
|
54818
|
+
] }),
|
|
54819
|
+
diffFile && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-t border-surface-800 flex flex-col max-h-48 min-h-0", children: [
|
|
54820
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-1 flex items-center justify-between flex-shrink-0 border-b border-surface-800", children: [
|
|
54821
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono text-surface-400 truncate", children: diffFile }),
|
|
54822
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setDiffFile(null), className: "text-surface-600 hover:text-white text-xs ml-2", children: "✕" })
|
|
54823
|
+
] }),
|
|
54824
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-auto flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiffViewer, { diff }) })
|
|
54825
|
+
] }),
|
|
54826
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-t border-surface-800 p-3 flex-shrink-0 flex flex-col gap-2", children: [
|
|
54827
|
+
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-red-400 truncate", title: error2, children: error2 }),
|
|
54828
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54829
|
+
"textarea",
|
|
54830
|
+
{
|
|
54831
|
+
value: message,
|
|
54832
|
+
onChange: (e) => setMessage(e.target.value),
|
|
54833
|
+
onKeyDown: (e) => {
|
|
54834
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) commit();
|
|
54835
|
+
},
|
|
54836
|
+
placeholder: "Commit message… (⌘↵ to commit)",
|
|
54837
|
+
rows: 2,
|
|
54838
|
+
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"
|
|
54839
|
+
}
|
|
54840
|
+
),
|
|
54841
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54842
|
+
"button",
|
|
54843
|
+
{
|
|
54844
|
+
onClick: commit,
|
|
54845
|
+
disabled: !message.trim() || !hasStaged,
|
|
54846
|
+
className: "w-full py-1.5 bg-blue-600 hover:bg-blue-500 disabled:opacity-40 disabled:cursor-not-allowed rounded text-xs font-medium transition-colors",
|
|
54847
|
+
children: [
|
|
54848
|
+
"Commit",
|
|
54849
|
+
hasStaged ? ` (${status.staged.length})` : ""
|
|
54850
|
+
]
|
|
54851
|
+
}
|
|
54852
|
+
)
|
|
54853
|
+
] })
|
|
54854
|
+
] });
|
|
54855
|
+
}
|
|
54856
|
+
function LogTab() {
|
|
54857
|
+
const [commits, setCommits] = reactExports.useState([]);
|
|
54858
|
+
const [loading, setLoading] = reactExports.useState(true);
|
|
54859
|
+
reactExports.useEffect(() => {
|
|
54860
|
+
electron$1.gitLog(100).then(setCommits).catch(() => setCommits([])).finally(() => setLoading(false));
|
|
54861
|
+
}, []);
|
|
54862
|
+
if (loading) return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-500 px-3 py-4", children: "Loading…" });
|
|
54863
|
+
if (commits.length === 0) return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-500 px-3 py-4", children: "No commits yet." });
|
|
54864
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: commits.map((c) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-2 border-b border-surface-800/50 hover:bg-surface-800/30", children: [
|
|
54865
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-2", children: [
|
|
54866
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono text-surface-600 shrink-0 mt-0.5", children: c.short }),
|
|
54867
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-surface-200 flex-1 line-clamp-2", children: c.message })
|
|
54868
|
+
] }),
|
|
54869
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-0.5 pl-9 flex gap-2 text-[10px] text-surface-600", children: [
|
|
54870
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: c.author }),
|
|
54871
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: new Date(c.date).toLocaleDateString() })
|
|
54872
|
+
] })
|
|
54873
|
+
] }, c.hash)) });
|
|
54874
|
+
}
|
|
54875
|
+
function BranchesTab({ onRefresh }) {
|
|
54876
|
+
const [branches, setBranches] = reactExports.useState([]);
|
|
54877
|
+
const [remotes, setRemotes] = reactExports.useState([]);
|
|
54878
|
+
const [loading, setLoading] = reactExports.useState(true);
|
|
54879
|
+
const [newBranch, setNewBranch] = reactExports.useState("");
|
|
54880
|
+
const [creating, setCreating] = reactExports.useState(false);
|
|
54881
|
+
const [addingRemote, setAddingRemote] = reactExports.useState(false);
|
|
54882
|
+
const [editingRemote, setEditingRemote] = reactExports.useState(null);
|
|
54883
|
+
const [remoteName, setRemoteName] = reactExports.useState("origin");
|
|
54884
|
+
const [remoteUrl, setRemoteUrl] = reactExports.useState("");
|
|
54885
|
+
const [editUrl, setEditUrl] = reactExports.useState("");
|
|
54886
|
+
const [error2, setError] = reactExports.useState(null);
|
|
54887
|
+
const load = reactExports.useCallback(() => {
|
|
54888
|
+
Promise.all([electron$1.gitBranches(), electron$1.gitRemotes()]).then(([b, r]) => {
|
|
54889
|
+
setBranches(b);
|
|
54890
|
+
setRemotes(r);
|
|
54891
|
+
}).catch(() => {
|
|
54892
|
+
}).finally(() => setLoading(false));
|
|
54893
|
+
}, []);
|
|
54894
|
+
reactExports.useEffect(() => {
|
|
54895
|
+
load();
|
|
54896
|
+
}, [load]);
|
|
54897
|
+
async function checkout(name2, remote2) {
|
|
54898
|
+
try {
|
|
54899
|
+
setError(null);
|
|
54900
|
+
const localName = remote2 ? name2.replace(/^origin\//, "") : name2;
|
|
54901
|
+
await electron$1.gitCheckout(localName, false);
|
|
54902
|
+
load();
|
|
54903
|
+
onRefresh();
|
|
54904
|
+
} catch (e) {
|
|
54905
|
+
setError(String(e));
|
|
54906
|
+
}
|
|
54907
|
+
}
|
|
54908
|
+
async function createBranch() {
|
|
54909
|
+
if (!newBranch.trim()) return;
|
|
54910
|
+
try {
|
|
54911
|
+
setError(null);
|
|
54912
|
+
await electron$1.gitCheckout(newBranch.trim(), true);
|
|
54913
|
+
setNewBranch("");
|
|
54914
|
+
setCreating(false);
|
|
54915
|
+
load();
|
|
54916
|
+
onRefresh();
|
|
54917
|
+
} catch (e) {
|
|
54918
|
+
setError(String(e));
|
|
54919
|
+
}
|
|
54920
|
+
}
|
|
54921
|
+
async function addRemote() {
|
|
54922
|
+
if (!remoteName.trim() || !remoteUrl.trim()) return;
|
|
54923
|
+
try {
|
|
54924
|
+
setError(null);
|
|
54925
|
+
await electron$1.gitAddRemote(remoteName.trim(), remoteUrl.trim());
|
|
54926
|
+
setRemoteName("origin");
|
|
54927
|
+
setRemoteUrl("");
|
|
54928
|
+
setAddingRemote(false);
|
|
54929
|
+
load();
|
|
54930
|
+
} catch (e) {
|
|
54931
|
+
setError(String(e));
|
|
54932
|
+
}
|
|
54933
|
+
}
|
|
54934
|
+
function startEdit(r) {
|
|
54935
|
+
setEditingRemote(r.name);
|
|
54936
|
+
setEditUrl(r.url);
|
|
54937
|
+
}
|
|
54938
|
+
async function saveRemoteUrl(name2) {
|
|
54939
|
+
if (!editUrl.trim()) return;
|
|
54940
|
+
try {
|
|
54941
|
+
setError(null);
|
|
54942
|
+
await electron$1.gitSetRemoteUrl(name2, editUrl.trim());
|
|
54943
|
+
setEditingRemote(null);
|
|
54944
|
+
load();
|
|
54945
|
+
} catch (e) {
|
|
54946
|
+
setError(String(e));
|
|
54947
|
+
}
|
|
54948
|
+
}
|
|
54949
|
+
async function removeRemote(name2) {
|
|
54950
|
+
try {
|
|
54951
|
+
setError(null);
|
|
54952
|
+
await electron$1.gitRemoveRemote(name2);
|
|
54953
|
+
load();
|
|
54954
|
+
} catch (e) {
|
|
54955
|
+
setError(String(e));
|
|
54956
|
+
}
|
|
54957
|
+
}
|
|
54958
|
+
const local = branches.filter((b) => !b.remote);
|
|
54959
|
+
const remote = branches.filter((b) => b.remote);
|
|
54960
|
+
if (loading) return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-500 px-3 py-4", children: "Loading…" });
|
|
54961
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto", children: [
|
|
54962
|
+
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-red-400 px-3 py-1 truncate", children: error2 }),
|
|
54963
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-2 border-b border-surface-800", children: creating ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-1.5", children: [
|
|
54964
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54965
|
+
"input",
|
|
54966
|
+
{
|
|
54967
|
+
autoFocus: true,
|
|
54968
|
+
value: newBranch,
|
|
54969
|
+
onChange: (e) => setNewBranch(e.target.value),
|
|
54970
|
+
onKeyDown: (e) => {
|
|
54971
|
+
if (e.key === "Enter") createBranch();
|
|
54972
|
+
if (e.key === "Escape") setCreating(false);
|
|
54973
|
+
},
|
|
54974
|
+
placeholder: "branch-name",
|
|
54975
|
+
className: "flex-1 bg-surface-800 border border-surface-700 rounded px-2 py-1 text-xs focus:outline-none focus:border-blue-500 placeholder-surface-600"
|
|
54976
|
+
}
|
|
54977
|
+
),
|
|
54978
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: createBranch, className: "text-xs text-blue-400 hover:text-blue-300 px-1", children: "Create" }),
|
|
54979
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setCreating(false), className: "text-xs text-surface-500 hover:text-white px-1", children: "✕" })
|
|
54980
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setCreating(true), className: "text-[11px] text-blue-400 hover:text-blue-300 transition-colors", children: "+ New branch" }) }),
|
|
54981
|
+
local.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { children: [
|
|
54982
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "px-3 py-1.5 text-[10px] uppercase tracking-widest text-surface-500 font-semibold", children: "Local" }),
|
|
54983
|
+
local.map((b) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54984
|
+
"button",
|
|
54985
|
+
{
|
|
54986
|
+
onClick: () => !b.current && checkout(b.name, false),
|
|
54987
|
+
className: `w-full flex items-center gap-2 px-3 py-1.5 text-left text-xs transition-colors ${b.current ? "text-blue-300 cursor-default" : "text-surface-300 hover:bg-surface-800/50"}`,
|
|
54988
|
+
children: [
|
|
54989
|
+
b.current ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-blue-400 text-[10px]", children: "●" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-3" }),
|
|
54990
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: b.name })
|
|
54991
|
+
]
|
|
54992
|
+
},
|
|
54993
|
+
b.name
|
|
54994
|
+
))
|
|
54995
|
+
] }),
|
|
54996
|
+
remote.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { children: [
|
|
54997
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "px-3 py-1.5 text-[10px] uppercase tracking-widest text-surface-500 font-semibold", children: "Remote branches" }),
|
|
54998
|
+
remote.map((b) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54999
|
+
"button",
|
|
55000
|
+
{
|
|
55001
|
+
onClick: () => checkout(b.name, true),
|
|
55002
|
+
className: "w-full flex items-center gap-2 px-3 py-1.5 text-left text-xs text-surface-400 hover:bg-surface-800/50 hover:text-surface-200 transition-colors",
|
|
55003
|
+
children: [
|
|
55004
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-3" }),
|
|
55005
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono", children: b.name })
|
|
55006
|
+
]
|
|
55007
|
+
},
|
|
55008
|
+
b.name
|
|
55009
|
+
))
|
|
55010
|
+
] }),
|
|
55011
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "border-t border-surface-800 mt-1", children: [
|
|
55012
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-1.5 flex items-center justify-between", children: [
|
|
55013
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[10px] uppercase tracking-widest text-surface-500 font-semibold", children: "Remotes" }),
|
|
55014
|
+
!addingRemote && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setAddingRemote(true), className: "text-[10px] text-blue-400 hover:text-blue-300 transition-colors", children: "+ Add" })
|
|
55015
|
+
] }),
|
|
55016
|
+
remotes.map((r) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-1 group", children: editingRemote === r.name ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
55017
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono text-surface-400", children: r.name }),
|
|
55018
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-1.5", children: [
|
|
55019
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55020
|
+
"input",
|
|
55021
|
+
{
|
|
55022
|
+
autoFocus: true,
|
|
55023
|
+
value: editUrl,
|
|
55024
|
+
onChange: (e) => setEditUrl(e.target.value),
|
|
55025
|
+
onKeyDown: (e) => {
|
|
55026
|
+
if (e.key === "Enter") saveRemoteUrl(r.name);
|
|
55027
|
+
if (e.key === "Escape") setEditingRemote(null);
|
|
55028
|
+
},
|
|
55029
|
+
className: "flex-1 bg-surface-800 border border-surface-700 rounded px-2 py-1 text-xs focus:outline-none focus:border-blue-500"
|
|
55030
|
+
}
|
|
55031
|
+
),
|
|
55032
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => saveRemoteUrl(r.name), className: "text-xs text-blue-400 hover:text-blue-300 px-1", children: "Save" }),
|
|
55033
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setEditingRemote(null), className: "text-xs text-surface-500 hover:text-white px-1", children: "✕" })
|
|
55034
|
+
] })
|
|
55035
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
55036
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-mono text-surface-300 shrink-0", children: r.name }),
|
|
55037
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono text-surface-600 truncate flex-1", children: r.url }),
|
|
55038
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55039
|
+
"button",
|
|
55040
|
+
{
|
|
55041
|
+
onClick: () => startEdit(r),
|
|
55042
|
+
className: "opacity-0 group-hover:opacity-100 text-[10px] text-surface-500 hover:text-blue-400 transition-all shrink-0",
|
|
55043
|
+
title: "Edit URL",
|
|
55044
|
+
children: "✎"
|
|
55045
|
+
}
|
|
55046
|
+
),
|
|
55047
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55048
|
+
"button",
|
|
55049
|
+
{
|
|
55050
|
+
onClick: () => removeRemote(r.name),
|
|
55051
|
+
className: "opacity-0 group-hover:opacity-100 text-[10px] text-surface-500 hover:text-red-400 transition-all shrink-0",
|
|
55052
|
+
title: "Remove remote",
|
|
55053
|
+
children: "✕"
|
|
55054
|
+
}
|
|
55055
|
+
)
|
|
55056
|
+
] }) }, r.name)),
|
|
55057
|
+
remotes.length === 0 && !addingRemote && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "px-3 pb-2 text-[11px] text-surface-600", children: "No remotes configured." }),
|
|
55058
|
+
addingRemote && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 pb-3 flex flex-col gap-1.5", children: [
|
|
55059
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55060
|
+
"input",
|
|
55061
|
+
{
|
|
55062
|
+
value: remoteName,
|
|
55063
|
+
onChange: (e) => setRemoteName(e.target.value),
|
|
55064
|
+
placeholder: "name (e.g. origin)",
|
|
55065
|
+
className: "w-full bg-surface-800 border border-surface-700 rounded px-2 py-1 text-xs focus:outline-none focus:border-blue-500 placeholder-surface-600"
|
|
55066
|
+
}
|
|
55067
|
+
),
|
|
55068
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55069
|
+
"input",
|
|
55070
|
+
{
|
|
55071
|
+
autoFocus: true,
|
|
55072
|
+
value: remoteUrl,
|
|
55073
|
+
onChange: (e) => setRemoteUrl(e.target.value),
|
|
55074
|
+
onKeyDown: (e) => {
|
|
55075
|
+
if (e.key === "Enter") addRemote();
|
|
55076
|
+
if (e.key === "Escape") setAddingRemote(false);
|
|
55077
|
+
},
|
|
55078
|
+
placeholder: "git@github.com:user/repo.git",
|
|
55079
|
+
className: "w-full bg-surface-800 border border-surface-700 rounded px-2 py-1 text-xs focus:outline-none focus:border-blue-500 placeholder-surface-600"
|
|
55080
|
+
}
|
|
55081
|
+
),
|
|
55082
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
|
|
55083
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: addRemote, className: "text-xs text-blue-400 hover:text-blue-300 transition-colors", children: "Add remote" }),
|
|
55084
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setAddingRemote(false), className: "text-xs text-surface-500 hover:text-white transition-colors", children: "Cancel" })
|
|
55085
|
+
] })
|
|
55086
|
+
] })
|
|
55087
|
+
] })
|
|
55088
|
+
] });
|
|
55089
|
+
}
|
|
55090
|
+
function detectPlatform(remotes) {
|
|
55091
|
+
const urls = remotes.map((r) => r.url.toLowerCase()).join(" ");
|
|
55092
|
+
if (urls.includes("github.com")) return "github";
|
|
55093
|
+
if (urls.includes("gitlab.com") || urls.includes("gitlab.")) return "gitlab";
|
|
55094
|
+
if (urls.includes("dev.azure.com") || urls.includes("visualstudio.com")) return "azure";
|
|
55095
|
+
return "unknown";
|
|
55096
|
+
}
|
|
55097
|
+
const NODE_LTS = "lts/*";
|
|
55098
|
+
function generateCiContent(platform, envName, tags2, secretVars) {
|
|
55099
|
+
const runCmd = [
|
|
55100
|
+
"api-spector run --workspace .",
|
|
55101
|
+
envName ? `--environment "${envName}"` : "",
|
|
55102
|
+
tags2 ? `--tags "${tags2}"` : "",
|
|
55103
|
+
"--output results.json"
|
|
55104
|
+
].filter(Boolean).join(" ");
|
|
55105
|
+
if (platform === "github") {
|
|
55106
|
+
const secretHint = secretVars.length ? ` # ⚠ Add these secrets in: Settings → Secrets and variables → Actions
|
|
55107
|
+
` + secretVars.map((v) => ` # ${v}`).join("\n") + "\n" : "";
|
|
55108
|
+
const envBlock = secretVars.length ? "\n env:\n" + secretVars.map((v) => ` ${v}: \${{ secrets.${v} }}`).join("\n") : "";
|
|
55109
|
+
return `name: API Tests
|
|
55110
|
+
|
|
55111
|
+
on:
|
|
55112
|
+
push:
|
|
55113
|
+
branches: [main]
|
|
55114
|
+
pull_request:
|
|
55115
|
+
|
|
55116
|
+
jobs:
|
|
55117
|
+
api-tests:
|
|
55118
|
+
runs-on: ubuntu-latest
|
|
55119
|
+
steps:
|
|
55120
|
+
- uses: actions/checkout@v4
|
|
55121
|
+
- uses: actions/setup-node@v4
|
|
55122
|
+
with:
|
|
55123
|
+
node-version: '${NODE_LTS}'
|
|
55124
|
+
- run: npm install -g @testsmith/api-spector
|
|
55125
|
+
${secretHint} - name: Run API tests
|
|
55126
|
+
run: ${runCmd}${envBlock}
|
|
55127
|
+
- name: Upload test results
|
|
55128
|
+
if: always()
|
|
55129
|
+
uses: actions/upload-artifact@v4
|
|
55130
|
+
with:
|
|
55131
|
+
name: api-test-results
|
|
55132
|
+
path: results.json
|
|
55133
|
+
`;
|
|
55134
|
+
}
|
|
55135
|
+
if (platform === "gitlab") {
|
|
55136
|
+
const secretHint = secretVars.length ? ` # ⚠ Add these in: Settings → CI/CD → Variables
|
|
55137
|
+
` + secretVars.map((v) => ` # ${v}`).join("\n") + "\n" : "";
|
|
55138
|
+
const envBlock = secretVars.length ? "\n variables:\n" + secretVars.map((v) => ` ${v}: $${v}`).join("\n") : "";
|
|
55139
|
+
return `api-tests:
|
|
55140
|
+
image: node:${NODE_LTS}
|
|
55141
|
+
stage: test
|
|
55142
|
+
before_script:
|
|
55143
|
+
- npm install -g @testsmith/api-spector
|
|
55144
|
+
${secretHint} script:
|
|
55145
|
+
- ${runCmd}${envBlock}
|
|
55146
|
+
artifacts:
|
|
55147
|
+
when: always
|
|
55148
|
+
paths:
|
|
55149
|
+
- results.json
|
|
55150
|
+
expire_in: 30 days
|
|
55151
|
+
`;
|
|
55152
|
+
}
|
|
55153
|
+
if (platform === "azure") {
|
|
55154
|
+
const secretHint = secretVars.length ? ` # ⚠ Add these in: Pipelines → Library → Variable groups (mark as secret)
|
|
55155
|
+
` + secretVars.map((v) => ` # ${v}`).join("\n") + "\n" : "";
|
|
55156
|
+
const envBlock = secretVars.length ? "\n env:\n" + secretVars.map((v) => ` ${v}: $(${v})`).join("\n") : "";
|
|
55157
|
+
return `trigger:
|
|
55158
|
+
- main
|
|
55159
|
+
|
|
55160
|
+
pool:
|
|
55161
|
+
vmImage: ubuntu-latest
|
|
55162
|
+
|
|
55163
|
+
steps:
|
|
55164
|
+
- task: NodeTool@0
|
|
55165
|
+
inputs:
|
|
55166
|
+
versionSpec: '${NODE_LTS}.x'
|
|
55167
|
+
displayName: 'Use Node.js ${NODE_LTS}'
|
|
55168
|
+
- script: npm install -g @testsmith/api-spector
|
|
55169
|
+
displayName: 'Install api Spector'
|
|
55170
|
+
${secretHint} - script: ${runCmd}
|
|
55171
|
+
displayName: 'Run API tests'${envBlock}
|
|
55172
|
+
- publish: results.json
|
|
55173
|
+
artifact: api-test-results
|
|
55174
|
+
displayName: 'Upload test results'
|
|
55175
|
+
condition: always()
|
|
55176
|
+
`;
|
|
55177
|
+
}
|
|
55178
|
+
return `# Unsupported platform — adapt as needed
|
|
55179
|
+
# ${runCmd}
|
|
55180
|
+
`;
|
|
55181
|
+
}
|
|
55182
|
+
function ciFilePath(platform) {
|
|
55183
|
+
if (platform === "github") return ".github/workflows/api-tests.yml";
|
|
55184
|
+
if (platform === "gitlab") return ".gitlab-ci.yml";
|
|
55185
|
+
if (platform === "azure") return "azure-pipelines.yml";
|
|
55186
|
+
return "ci.yml";
|
|
55187
|
+
}
|
|
55188
|
+
function CiTab() {
|
|
55189
|
+
const environments = useStore((s) => s.environments);
|
|
55190
|
+
const envList = Object.values(environments);
|
|
55191
|
+
const [remotes, setRemotes] = reactExports.useState([]);
|
|
55192
|
+
const [platform, setPlatform] = reactExports.useState("unknown");
|
|
55193
|
+
const [envId, setEnvId] = reactExports.useState("");
|
|
55194
|
+
const [tags2, setTags] = reactExports.useState("");
|
|
55195
|
+
const [preview, setPreview] = reactExports.useState("");
|
|
55196
|
+
const [written, setWritten] = reactExports.useState(false);
|
|
55197
|
+
const [error2, setError] = reactExports.useState(null);
|
|
55198
|
+
reactExports.useEffect(() => {
|
|
55199
|
+
electron$1.gitRemotes().then((r) => {
|
|
55200
|
+
setRemotes(r);
|
|
55201
|
+
const detected = detectPlatform(r);
|
|
55202
|
+
setPlatform(detected);
|
|
55203
|
+
}).catch(() => {
|
|
55204
|
+
});
|
|
55205
|
+
}, []);
|
|
55206
|
+
reactExports.useEffect(() => {
|
|
55207
|
+
const env = envList.find((e) => e.data.id === envId);
|
|
55208
|
+
const secretVars = env ? env.data.variables.filter((v) => v.secret && v.enabled).map((v) => v.key) : [];
|
|
55209
|
+
const envName = env?.data.name ?? "";
|
|
55210
|
+
setPreview(generateCiContent(platform, envName, tags2, secretVars));
|
|
55211
|
+
setWritten(false);
|
|
55212
|
+
}, [platform, envId, tags2, environments]);
|
|
55213
|
+
async function write() {
|
|
55214
|
+
try {
|
|
55215
|
+
setError(null);
|
|
55216
|
+
await electron$1.gitWriteCiFile(ciFilePath(platform), preview);
|
|
55217
|
+
setWritten(true);
|
|
55218
|
+
} catch (e) {
|
|
55219
|
+
setError(String(e));
|
|
55220
|
+
}
|
|
55221
|
+
}
|
|
55222
|
+
const platformLabels = {
|
|
55223
|
+
github: "GitHub Actions",
|
|
55224
|
+
gitlab: "GitLab CI",
|
|
55225
|
+
azure: "Azure Pipelines",
|
|
55226
|
+
unknown: "Unknown"
|
|
55227
|
+
};
|
|
55228
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto", children: [
|
|
55229
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-3 flex flex-col gap-3 border-b border-surface-800", children: [
|
|
55230
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
55231
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-[10px] uppercase tracking-widest text-surface-500 font-semibold", children: "Platform" }),
|
|
55232
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55233
|
+
"select",
|
|
55234
|
+
{
|
|
55235
|
+
value: platform,
|
|
55236
|
+
onChange: (e) => setPlatform(e.target.value),
|
|
55237
|
+
className: "bg-surface-800 border border-surface-700 rounded px-2 py-1.5 text-xs focus:outline-none focus:border-blue-500",
|
|
55238
|
+
children: ["github", "gitlab", "azure"].map((p) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: p, children: platformLabels[p] }, p))
|
|
55239
|
+
}
|
|
55240
|
+
),
|
|
55241
|
+
remotes.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-surface-600", children: [
|
|
55242
|
+
"Detected from remote: ",
|
|
55243
|
+
platformLabels[detectPlatform(remotes)]
|
|
55244
|
+
] })
|
|
55245
|
+
] }),
|
|
55246
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
55247
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-[10px] uppercase tracking-widest text-surface-500 font-semibold", children: "Environment" }),
|
|
55248
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
55249
|
+
"select",
|
|
55250
|
+
{
|
|
55251
|
+
value: envId,
|
|
55252
|
+
onChange: (e) => setEnvId(e.target.value),
|
|
55253
|
+
className: "bg-surface-800 border border-surface-700 rounded px-2 py-1.5 text-xs focus:outline-none focus:border-blue-500",
|
|
55254
|
+
children: [
|
|
55255
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: "— none —" }),
|
|
55256
|
+
envList.map((e) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: e.data.id, children: e.data.name }, e.data.id))
|
|
55257
|
+
]
|
|
55258
|
+
}
|
|
55259
|
+
),
|
|
55260
|
+
envId && (() => {
|
|
55261
|
+
const env = envList.find((e) => e.data.id === envId);
|
|
55262
|
+
const secrets = env?.data.variables.filter((v) => v.secret && v.enabled) ?? [];
|
|
55263
|
+
return secrets.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] text-amber-400/80", children: [
|
|
55264
|
+
secrets.length,
|
|
55265
|
+
" secret variable",
|
|
55266
|
+
secrets.length !== 1 ? "s" : "",
|
|
55267
|
+
" will be mapped to CI secrets"
|
|
55268
|
+
] }) : null;
|
|
55269
|
+
})()
|
|
55270
|
+
] }),
|
|
55271
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
55272
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-[10px] uppercase tracking-widest text-surface-500 font-semibold", children: "Tags (optional)" }),
|
|
55273
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55274
|
+
"input",
|
|
55275
|
+
{
|
|
55276
|
+
value: tags2,
|
|
55277
|
+
onChange: (e) => setTags(e.target.value),
|
|
55278
|
+
placeholder: "e.g. smoke, regression",
|
|
55279
|
+
className: "bg-surface-800 border border-surface-700 rounded px-2 py-1.5 text-xs focus:outline-none focus:border-blue-500 placeholder-surface-600"
|
|
55280
|
+
}
|
|
55281
|
+
)
|
|
55282
|
+
] }),
|
|
55283
|
+
error2 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] text-red-400", children: error2 }),
|
|
55284
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
55285
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
55286
|
+
"button",
|
|
55287
|
+
{
|
|
55288
|
+
onClick: write,
|
|
55289
|
+
className: "flex-1 py-1.5 bg-blue-600 hover:bg-blue-500 rounded text-xs font-medium transition-colors",
|
|
55290
|
+
children: [
|
|
55291
|
+
"Write ",
|
|
55292
|
+
ciFilePath(platform)
|
|
55293
|
+
]
|
|
55294
|
+
}
|
|
55295
|
+
),
|
|
55296
|
+
written && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] text-emerald-400", children: "✓ Written" })
|
|
55297
|
+
] })
|
|
55298
|
+
] }),
|
|
55299
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 overflow-auto", children: [
|
|
55300
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "px-3 pt-2 pb-1 text-[10px] uppercase tracking-widest text-surface-600 font-semibold", children: "Preview" }),
|
|
55301
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "px-3 pb-3 text-[10px] font-mono text-surface-400 leading-relaxed whitespace-pre-wrap", children: preview })
|
|
55302
|
+
] })
|
|
55303
|
+
] });
|
|
55304
|
+
}
|
|
55305
|
+
function GitPanel() {
|
|
55306
|
+
const [isRepo, setIsRepo] = reactExports.useState(null);
|
|
55307
|
+
const [status, setStatus] = reactExports.useState(null);
|
|
55308
|
+
const [tab, setTab] = reactExports.useState("changes");
|
|
55309
|
+
const [loading, setLoading] = reactExports.useState(true);
|
|
55310
|
+
const refresh = reactExports.useCallback(async () => {
|
|
55311
|
+
try {
|
|
55312
|
+
const repo = await electron$1.gitIsRepo();
|
|
55313
|
+
setIsRepo(repo);
|
|
55314
|
+
if (repo) setStatus(await electron$1.gitStatus());
|
|
55315
|
+
} catch {
|
|
55316
|
+
setIsRepo(false);
|
|
55317
|
+
} finally {
|
|
55318
|
+
setLoading(false);
|
|
55319
|
+
}
|
|
55320
|
+
}, []);
|
|
55321
|
+
reactExports.useEffect(() => {
|
|
55322
|
+
refresh();
|
|
55323
|
+
}, [refresh]);
|
|
55324
|
+
if (loading) {
|
|
55325
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 flex items-center justify-center text-xs text-surface-500", children: "Loading…" });
|
|
55326
|
+
}
|
|
55327
|
+
if (!isRepo) {
|
|
55328
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col items-center justify-center gap-3 px-4 text-center", children: [
|
|
55329
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-surface-400", children: "Not a git repository." }),
|
|
55330
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55331
|
+
"button",
|
|
55332
|
+
{
|
|
55333
|
+
onClick: async () => {
|
|
55334
|
+
await electron$1.gitInit();
|
|
55335
|
+
refresh();
|
|
55336
|
+
},
|
|
55337
|
+
className: "px-3 py-1.5 bg-surface-800 hover:bg-surface-700 rounded text-xs transition-colors",
|
|
55338
|
+
children: "git init"
|
|
55339
|
+
}
|
|
55340
|
+
)
|
|
55341
|
+
] });
|
|
55342
|
+
}
|
|
55343
|
+
const totalChanges = status ? status.staged.length + status.unstaged.length + status.untracked.length : 0;
|
|
55344
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col flex-1 min-h-0", children: [
|
|
55345
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex border-b border-surface-800 flex-shrink-0", children: [
|
|
55346
|
+
["changes", "log", "branches", "ci"].map((t2) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
55347
|
+
"button",
|
|
55348
|
+
{
|
|
55349
|
+
onClick: () => setTab(t2),
|
|
55350
|
+
className: `flex-1 py-1.5 text-[11px] capitalize transition-colors border-b-2 -mb-px ${tab === t2 ? "border-blue-500 text-white" : "border-transparent text-surface-400 hover:text-white"}`,
|
|
55351
|
+
children: [
|
|
55352
|
+
t2,
|
|
55353
|
+
t2 === "changes" && totalChanges > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-1 bg-surface-700 text-surface-300 rounded px-1 text-[9px]", children: totalChanges })
|
|
55354
|
+
]
|
|
55355
|
+
},
|
|
55356
|
+
t2
|
|
55357
|
+
)),
|
|
55358
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55359
|
+
"button",
|
|
55360
|
+
{
|
|
55361
|
+
onClick: refresh,
|
|
55362
|
+
title: "Refresh",
|
|
55363
|
+
className: "px-2 text-surface-600 hover:text-surface-300 transition-colors border-b-2 border-transparent -mb-px",
|
|
55364
|
+
children: "↺"
|
|
55365
|
+
}
|
|
55366
|
+
)
|
|
55367
|
+
] }),
|
|
55368
|
+
tab === "changes" && status && /* @__PURE__ */ jsxRuntimeExports.jsx(ChangesTab, { status, onRefresh: refresh }),
|
|
55369
|
+
tab === "log" && /* @__PURE__ */ jsxRuntimeExports.jsx(LogTab, {}),
|
|
55370
|
+
tab === "branches" && /* @__PURE__ */ jsxRuntimeExports.jsx(BranchesTab, { onRefresh: refresh }),
|
|
55371
|
+
tab === "ci" && /* @__PURE__ */ jsxRuntimeExports.jsx(CiTab, {})
|
|
55372
|
+
] });
|
|
55373
|
+
}
|
|
54568
55374
|
function CommandPalette() {
|
|
54569
55375
|
const open = useStore((s) => s.commandPaletteOpen);
|
|
54570
55376
|
const setOpen = useStore((s) => s.setCommandPaletteOpen);
|
|
@@ -54715,6 +55521,15 @@ function IconMock() {
|
|
|
54715
55521
|
function IconContract() {
|
|
54716
55522
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: "0 0 20 20", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M10 2a1 1 0 011 1v1.323l3.954 1.582 1.599-.8a1 1 0 01.894 1.79l-1.233.616 1.738 5.42a1 1 0 01-.285 1.05A3.989 3.989 0 0115 14a3.989 3.989 0 01-2.667-1.019 1 1 0 01-.285-1.05l1.715-5.349L11 5.477V17H13a1 1 0 110 2H7a1 1 0 110-2h2V5.477L6.237 6.582l1.715 5.349a1 1 0 01-.285 1.05A3.989 3.989 0 015 14a3.989 3.989 0 01-2.667-1.019 1 1 0 01-.285-1.05l1.738-5.42-1.233-.617a1 1 0 01.894-1.788l1.599.799L9 3.323V3a1 1 0 011-1z", clipRule: "evenodd" }) });
|
|
54717
55523
|
}
|
|
55524
|
+
function IconGit() {
|
|
55525
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "18", height: "18", children: [
|
|
55526
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "6", cy: "6", r: "2.5" }),
|
|
55527
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "6", cy: "18", r: "2.5" }),
|
|
55528
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "18", cy: "6", r: "2.5" }),
|
|
55529
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6", y1: "8.5", x2: "6", y2: "15.5" }),
|
|
55530
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M6 8.5 C6 13 18 10 18 8.5" })
|
|
55531
|
+
] });
|
|
55532
|
+
}
|
|
54718
55533
|
function ActivityBarBtn({
|
|
54719
55534
|
active,
|
|
54720
55535
|
onClick,
|
|
@@ -54722,18 +55537,20 @@ function ActivityBarBtn({
|
|
|
54722
55537
|
badge,
|
|
54723
55538
|
children
|
|
54724
55539
|
}) {
|
|
54725
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
54726
|
-
|
|
54727
|
-
|
|
54728
|
-
|
|
54729
|
-
|
|
54730
|
-
|
|
54731
|
-
|
|
54732
|
-
|
|
54733
|
-
|
|
54734
|
-
|
|
54735
|
-
|
|
54736
|
-
|
|
55540
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative group/ab", children: [
|
|
55541
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
55542
|
+
"button",
|
|
55543
|
+
{
|
|
55544
|
+
onClick,
|
|
55545
|
+
className: `relative w-10 h-10 flex items-center justify-center rounded transition-colors ${active ? "text-white bg-surface-800" : "text-surface-600 hover:text-surface-300 hover:bg-surface-800/50"}`,
|
|
55546
|
+
children: [
|
|
55547
|
+
children,
|
|
55548
|
+
badge !== void 0 && badge > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute top-1 right-1 text-[9px] bg-surface-600 text-white rounded-full w-3.5 h-3.5 flex items-center justify-center font-medium leading-none", children: badge > 9 ? "9+" : badge })
|
|
55549
|
+
]
|
|
55550
|
+
}
|
|
55551
|
+
),
|
|
55552
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pointer-events-none absolute left-full top-1/2 -translate-y-1/2 ml-2 z-50 hidden group-hover/ab:block", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap rounded px-2 py-1 text-[11px] bg-[#1e1b2e] text-gray-200 border border-white/10 shadow-lg", children: title2 }) })
|
|
55553
|
+
] });
|
|
54737
55554
|
}
|
|
54738
55555
|
const TAB_METHOD_COLORS = {
|
|
54739
55556
|
GET: "text-emerald-400",
|
|
@@ -54821,7 +55638,7 @@ function App() {
|
|
|
54821
55638
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "#6aa3c8" }, children: "Spector" }),
|
|
54822
55639
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-2 text-[10px] font-normal opacity-50", children: [
|
|
54823
55640
|
"v",
|
|
54824
|
-
"0.1.
|
|
55641
|
+
"0.1.1"
|
|
54825
55642
|
] })
|
|
54826
55643
|
] }) }),
|
|
54827
55644
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Toolbar, { onOpenDocs: () => setDocsModalOpen(true) }),
|
|
@@ -54863,11 +55680,20 @@ function App() {
|
|
|
54863
55680
|
title: "Contract testing",
|
|
54864
55681
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(IconContract, {})
|
|
54865
55682
|
}
|
|
55683
|
+
),
|
|
55684
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
55685
|
+
ActivityBarBtn,
|
|
55686
|
+
{
|
|
55687
|
+
active: sidebarOpen && sidebarTab === "git",
|
|
55688
|
+
onClick: () => selectPanel("git"),
|
|
55689
|
+
title: "Git",
|
|
55690
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(IconGit, {})
|
|
55691
|
+
}
|
|
54866
55692
|
)
|
|
54867
55693
|
] }),
|
|
54868
55694
|
sidebarOpen ? /* @__PURE__ */ jsxRuntimeExports.jsxs("aside", { className: "w-64 flex-shrink-0 border-r border-surface-800 flex flex-col overflow-hidden", children: [
|
|
54869
55695
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "px-3 py-2 flex items-center justify-between border-b border-surface-800 flex-shrink-0", children: [
|
|
54870
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-surface-600", children: sidebarTab === "collections" ? "Collections" : sidebarTab === "history" ? "History" : sidebarTab === "mocks" ? "Mocks" : "Contracts" }),
|
|
55696
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-surface-600", children: sidebarTab === "collections" ? "Collections" : sidebarTab === "history" ? "History" : sidebarTab === "mocks" ? "Mocks" : sidebarTab === "git" ? "Git" : "Contracts" }),
|
|
54871
55697
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
54872
55698
|
sidebarTab === "history" && historyCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] bg-surface-700 text-surface-400 rounded px-1.5 py-0.5", children: historyCount }),
|
|
54873
55699
|
sidebarTab === "collections" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -54890,7 +55716,7 @@ function App() {
|
|
|
54890
55716
|
)
|
|
54891
55717
|
] })
|
|
54892
55718
|
] }),
|
|
54893
|
-
sidebarTab === "collections" ? /* @__PURE__ */ jsxRuntimeExports.jsx(CollectionTree, {}) : sidebarTab === "history" ? /* @__PURE__ */ jsxRuntimeExports.jsx(HistoryPanel, {}) : sidebarTab === "mocks" ? /* @__PURE__ */ jsxRuntimeExports.jsx(MockPanel, {}) : /* @__PURE__ */ jsxRuntimeExports.jsx(ContractPanel, {})
|
|
55719
|
+
sidebarTab === "collections" ? /* @__PURE__ */ jsxRuntimeExports.jsx(CollectionTree, {}) : sidebarTab === "history" ? /* @__PURE__ */ jsxRuntimeExports.jsx(HistoryPanel, {}) : sidebarTab === "mocks" ? /* @__PURE__ */ jsxRuntimeExports.jsx(MockPanel, {}) : sidebarTab === "git" ? /* @__PURE__ */ jsxRuntimeExports.jsx(GitPanel, {}) : /* @__PURE__ */ jsxRuntimeExports.jsx(ContractPanel, {})
|
|
54894
55720
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
54895
55721
|
"button",
|
|
54896
55722
|
{
|