@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
package/out/main/index.js
CHANGED
|
@@ -35,6 +35,7 @@ const http = require("http");
|
|
|
35
35
|
const WebSocket = require("ws");
|
|
36
36
|
const https = require("https");
|
|
37
37
|
const Ajv = require("ajv");
|
|
38
|
+
const simpleGit = require("simple-git");
|
|
38
39
|
require("crypto");
|
|
39
40
|
require("dayjs");
|
|
40
41
|
require("vm");
|
|
@@ -86,7 +87,7 @@ function registerFileHandlers(ipc) {
|
|
|
86
87
|
await requestHandler.loadGlobals(workspaceDir);
|
|
87
88
|
await promises.mkdir(path.join(workspaceDir, "collections"), { recursive: true });
|
|
88
89
|
await promises.mkdir(path.join(workspaceDir, "environments"), { recursive: true });
|
|
89
|
-
const gitignore = "# api Spector — never commit secrets\n*.secrets\n.env.local\n";
|
|
90
|
+
const gitignore = "# api Spector — never commit secrets\n*.secrets\n.env.local\n\n# Dependencies\nnode_modules/\n";
|
|
90
91
|
await atomicWrite(path.join(workspaceDir, ".gitignore"), gitignore);
|
|
91
92
|
const ws = {
|
|
92
93
|
version: "1.0",
|
|
@@ -3436,6 +3437,120 @@ function registerContractHandlers(ipc) {
|
|
|
3436
3437
|
return schema ? JSON.stringify(schema, null, 2) : null;
|
|
3437
3438
|
});
|
|
3438
3439
|
}
|
|
3440
|
+
function git() {
|
|
3441
|
+
const dir = getWorkspaceDir();
|
|
3442
|
+
if (!dir) throw new Error("No workspace open");
|
|
3443
|
+
return simpleGit.simpleGit(dir);
|
|
3444
|
+
}
|
|
3445
|
+
function registerGitHandlers(ipc) {
|
|
3446
|
+
ipc.handle("git:isRepo", async () => {
|
|
3447
|
+
try {
|
|
3448
|
+
await git().revparse(["--git-dir"]);
|
|
3449
|
+
return true;
|
|
3450
|
+
} catch {
|
|
3451
|
+
return false;
|
|
3452
|
+
}
|
|
3453
|
+
});
|
|
3454
|
+
ipc.handle("git:init", async () => {
|
|
3455
|
+
await git().init();
|
|
3456
|
+
});
|
|
3457
|
+
ipc.handle("git:status", async () => {
|
|
3458
|
+
const result = await git().status();
|
|
3459
|
+
return {
|
|
3460
|
+
staged: result.staged.map((f) => ({ path: f, status: resolveStatus(result, f, true) })),
|
|
3461
|
+
unstaged: result.modified.filter((f) => !result.staged.includes(f)).concat(result.deleted.filter((f) => !result.staged.includes(f))).map((f) => ({ path: f, status: resolveStatus(result, f, false) })),
|
|
3462
|
+
untracked: result.not_added.map((f) => ({ path: f, status: "untracked" })),
|
|
3463
|
+
branch: result.current ?? "",
|
|
3464
|
+
ahead: result.ahead,
|
|
3465
|
+
behind: result.behind,
|
|
3466
|
+
remote: result.tracking ?? null
|
|
3467
|
+
};
|
|
3468
|
+
});
|
|
3469
|
+
ipc.handle("git:diff", async (_e, filePath) => {
|
|
3470
|
+
if (filePath) return git().diff(["--", filePath]);
|
|
3471
|
+
return git().diff();
|
|
3472
|
+
});
|
|
3473
|
+
ipc.handle("git:diffStaged", async (_e, filePath) => {
|
|
3474
|
+
if (filePath) return git().diff(["--cached", "--", filePath]);
|
|
3475
|
+
return git().diff(["--cached"]);
|
|
3476
|
+
});
|
|
3477
|
+
ipc.handle("git:stage", async (_e, paths) => {
|
|
3478
|
+
await git().add(paths);
|
|
3479
|
+
});
|
|
3480
|
+
ipc.handle("git:unstage", async (_e, paths) => {
|
|
3481
|
+
await git().reset(["HEAD", "--", ...paths]);
|
|
3482
|
+
});
|
|
3483
|
+
ipc.handle("git:stageAll", async () => {
|
|
3484
|
+
await git().add(["."]);
|
|
3485
|
+
});
|
|
3486
|
+
ipc.handle("git:commit", async (_e, message) => {
|
|
3487
|
+
await git().commit(message);
|
|
3488
|
+
});
|
|
3489
|
+
ipc.handle("git:log", async (_e, limit = 50) => {
|
|
3490
|
+
const result = await git().log({ maxCount: limit });
|
|
3491
|
+
return result.all.map((c) => ({
|
|
3492
|
+
hash: c.hash,
|
|
3493
|
+
short: c.hash.slice(0, 7),
|
|
3494
|
+
message: c.message,
|
|
3495
|
+
author: c.author_name,
|
|
3496
|
+
email: c.author_email,
|
|
3497
|
+
date: c.date
|
|
3498
|
+
}));
|
|
3499
|
+
});
|
|
3500
|
+
ipc.handle("git:branches", async () => {
|
|
3501
|
+
const result = await git().branch(["-a", "--format=%(refname:short)|%(objectname:short)|%(upstream:short)|%(upstream:track)"]);
|
|
3502
|
+
return result.all.filter((name) => !name.includes("HEAD")).map((name) => ({
|
|
3503
|
+
name: name.replace(/^remotes\//, ""),
|
|
3504
|
+
current: name === result.current,
|
|
3505
|
+
remote: name.startsWith("remotes/")
|
|
3506
|
+
}));
|
|
3507
|
+
});
|
|
3508
|
+
ipc.handle("git:checkout", async (_e, branch, create) => {
|
|
3509
|
+
if (create) await git().checkoutLocalBranch(branch);
|
|
3510
|
+
else await git().checkout(branch);
|
|
3511
|
+
});
|
|
3512
|
+
ipc.handle("git:pull", async () => {
|
|
3513
|
+
await git().pull();
|
|
3514
|
+
});
|
|
3515
|
+
ipc.handle("git:push", async (_e, setUpstream) => {
|
|
3516
|
+
if (setUpstream) {
|
|
3517
|
+
const status = await git().status();
|
|
3518
|
+
await git().push(["--set-upstream", "origin", status.current ?? "main"]);
|
|
3519
|
+
} else {
|
|
3520
|
+
await git().push();
|
|
3521
|
+
}
|
|
3522
|
+
});
|
|
3523
|
+
ipc.handle("git:remotes", async () => {
|
|
3524
|
+
const result = await git().getRemotes(true);
|
|
3525
|
+
return result.map((r) => ({ name: r.name, url: r.refs.fetch || r.refs.push || "" }));
|
|
3526
|
+
});
|
|
3527
|
+
ipc.handle("git:addRemote", async (_e, name, url) => {
|
|
3528
|
+
await git().addRemote(name, url);
|
|
3529
|
+
});
|
|
3530
|
+
ipc.handle("git:setRemoteUrl", async (_e, name, url) => {
|
|
3531
|
+
await git().remote(["set-url", name, url]);
|
|
3532
|
+
});
|
|
3533
|
+
ipc.handle("git:removeRemote", async (_e, name) => {
|
|
3534
|
+
await git().removeRemote(name);
|
|
3535
|
+
});
|
|
3536
|
+
ipc.handle("git:writeCiFile", async (_e, relPath, content) => {
|
|
3537
|
+
const wsDir = getWorkspaceDir();
|
|
3538
|
+
if (!wsDir) throw new Error("No workspace open");
|
|
3539
|
+
const fullPath = path.join(wsDir, relPath);
|
|
3540
|
+
await promises.mkdir(path.dirname(fullPath), { recursive: true });
|
|
3541
|
+
await promises.writeFile(fullPath, content, "utf8");
|
|
3542
|
+
});
|
|
3543
|
+
}
|
|
3544
|
+
function resolveStatus(result, filePath, staged) {
|
|
3545
|
+
if (staged) {
|
|
3546
|
+
if (result.created.includes(filePath)) return "added";
|
|
3547
|
+
if (result.deleted.includes(filePath)) return "deleted";
|
|
3548
|
+
if (result.renamed.find((r) => r.to === filePath || r.from === filePath)) return "renamed";
|
|
3549
|
+
return "modified";
|
|
3550
|
+
}
|
|
3551
|
+
if (result.deleted.includes(filePath)) return "deleted";
|
|
3552
|
+
return "modified";
|
|
3553
|
+
}
|
|
3439
3554
|
if (process.env.ELECTRON_NO_SANDBOX === "1") {
|
|
3440
3555
|
electron.app.commandLine.appendSwitch("no-sandbox");
|
|
3441
3556
|
electron.app.commandLine.appendSwitch("disable-features", "RendererCodeIntegrity");
|
|
@@ -3536,6 +3651,7 @@ electron.app.whenReady().then(async () => {
|
|
|
3536
3651
|
registerSoapHandlers(electron.ipcMain);
|
|
3537
3652
|
registerDocsHandlers(electron.ipcMain);
|
|
3538
3653
|
registerContractHandlers(electron.ipcMain);
|
|
3654
|
+
registerGitHandlers(electron.ipcMain);
|
|
3539
3655
|
createWindow();
|
|
3540
3656
|
electron.app.on("activate", () => {
|
|
3541
3657
|
if (electron.BrowserWindow.getAllWindows().length === 0) createWindow();
|
package/out/main/runner.js
CHANGED
|
@@ -123,9 +123,18 @@ function parseArgs(argv) {
|
|
|
123
123
|
}
|
|
124
124
|
return args;
|
|
125
125
|
}
|
|
126
|
+
async function resolveWorkspacePath(wsPath) {
|
|
127
|
+
const s = await promises.stat(wsPath);
|
|
128
|
+
if (!s.isDirectory()) return wsPath;
|
|
129
|
+
const entries = await promises.readdir(wsPath);
|
|
130
|
+
const spector = entries.find((e) => e.endsWith(".spector"));
|
|
131
|
+
if (!spector) throw new Error(`No .spector workspace file found in directory: ${wsPath}`);
|
|
132
|
+
return path.join(wsPath, spector);
|
|
133
|
+
}
|
|
126
134
|
async function loadWorkspace(wsPath) {
|
|
127
|
-
const
|
|
128
|
-
|
|
135
|
+
const resolved = await resolveWorkspacePath(wsPath);
|
|
136
|
+
const raw = await promises.readFile(resolved, "utf8");
|
|
137
|
+
return { workspace: JSON.parse(raw), dir: path.dirname(path.resolve(resolved)) };
|
|
129
138
|
}
|
|
130
139
|
async function loadCollections(workspace, dir) {
|
|
131
140
|
const cols = [];
|
package/out/preload/index.js
CHANGED
|
@@ -81,6 +81,26 @@ const api = {
|
|
|
81
81
|
inferContractSchema: (jsonBody) => electron.ipcRenderer.invoke("contract:inferSchema", jsonBody),
|
|
82
82
|
// ─── Script hooks ─────────────────────────────────────────────────────────
|
|
83
83
|
runScriptHook: (payload) => electron.ipcRenderer.invoke("script:run-hook", payload),
|
|
84
|
+
// ─── Git ──────────────────────────────────────────────────────────────────
|
|
85
|
+
gitIsRepo: () => electron.ipcRenderer.invoke("git:isRepo"),
|
|
86
|
+
gitInit: () => electron.ipcRenderer.invoke("git:init"),
|
|
87
|
+
gitStatus: () => electron.ipcRenderer.invoke("git:status"),
|
|
88
|
+
gitDiff: (filePath) => electron.ipcRenderer.invoke("git:diff", filePath),
|
|
89
|
+
gitDiffStaged: (filePath) => electron.ipcRenderer.invoke("git:diffStaged", filePath),
|
|
90
|
+
gitStage: (paths) => electron.ipcRenderer.invoke("git:stage", paths),
|
|
91
|
+
gitUnstage: (paths) => electron.ipcRenderer.invoke("git:unstage", paths),
|
|
92
|
+
gitStageAll: () => electron.ipcRenderer.invoke("git:stageAll"),
|
|
93
|
+
gitCommit: (message) => electron.ipcRenderer.invoke("git:commit", message),
|
|
94
|
+
gitLog: (limit) => electron.ipcRenderer.invoke("git:log", limit),
|
|
95
|
+
gitBranches: () => electron.ipcRenderer.invoke("git:branches"),
|
|
96
|
+
gitCheckout: (branch, create) => electron.ipcRenderer.invoke("git:checkout", branch, create),
|
|
97
|
+
gitPull: () => electron.ipcRenderer.invoke("git:pull"),
|
|
98
|
+
gitPush: (setUpstream) => electron.ipcRenderer.invoke("git:push", setUpstream),
|
|
99
|
+
gitRemotes: () => electron.ipcRenderer.invoke("git:remotes"),
|
|
100
|
+
gitAddRemote: (name, url) => electron.ipcRenderer.invoke("git:addRemote", name, url),
|
|
101
|
+
gitSetRemoteUrl: (name, url) => electron.ipcRenderer.invoke("git:setRemoteUrl", name, url),
|
|
102
|
+
gitRemoveRemote: (name) => electron.ipcRenderer.invoke("git:removeRemote", name),
|
|
103
|
+
gitWriteCiFile: (relPath, content) => electron.ipcRenderer.invoke("git:writeCiFile", relPath, content),
|
|
84
104
|
// ─── Zoom ─────────────────────────────────────────────────────────────────
|
|
85
105
|
setZoomFactor: (factor) => electron.webFrame.setZoomFactor(factor),
|
|
86
106
|
// ─── Platform ─────────────────────────────────────────────────────────────
|