wasper-cli 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -83
- package/dist/cli.js +1829 -833
- package/dist/index.js +72 -28
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3607,7 +3607,7 @@ var package_default;
|
|
|
3607
3607
|
var init_package = __esm(() => {
|
|
3608
3608
|
package_default = {
|
|
3609
3609
|
name: "wasper-cli",
|
|
3610
|
-
version: "0.3.
|
|
3610
|
+
version: "0.3.2",
|
|
3611
3611
|
description: "Host an MCP server + API proxy from any OpenAPI spec. Like Drizzle Studio, but for APIs.",
|
|
3612
3612
|
type: "module",
|
|
3613
3613
|
homepage: "https://wasper.site",
|
|
@@ -6581,25 +6581,69 @@ var init_routes = __esm(() => {
|
|
|
6581
6581
|
// src/daemon.ts
|
|
6582
6582
|
import { join as join2 } from "path";
|
|
6583
6583
|
import { homedir as homedir2 } from "os";
|
|
6584
|
-
import { mkdir, readFile, writeFile, unlink } from "fs/promises";
|
|
6584
|
+
import { mkdir, readFile, readdir, writeFile, unlink } from "fs/promises";
|
|
6585
6585
|
async function ensureDir() {
|
|
6586
|
-
await mkdir(
|
|
6586
|
+
await mkdir(WASPER_DIR, { recursive: true });
|
|
6587
|
+
}
|
|
6588
|
+
function stateFile(port) {
|
|
6589
|
+
return join2(WASPER_DIR, `server-${port}.json`);
|
|
6590
|
+
}
|
|
6591
|
+
function logFile(port) {
|
|
6592
|
+
return join2(WASPER_DIR, `server-${port}.log`);
|
|
6587
6593
|
}
|
|
6588
6594
|
async function writeDaemonState(s) {
|
|
6589
6595
|
await ensureDir();
|
|
6590
|
-
await writeFile(
|
|
6596
|
+
await writeFile(stateFile(s.port), JSON.stringify(s, null, 2), "utf-8");
|
|
6591
6597
|
}
|
|
6592
|
-
async function
|
|
6598
|
+
async function readAllDaemonStates() {
|
|
6593
6599
|
try {
|
|
6594
|
-
const
|
|
6595
|
-
|
|
6600
|
+
const files = await readdir(WASPER_DIR);
|
|
6601
|
+
const states = [];
|
|
6602
|
+
for (const f of files) {
|
|
6603
|
+
if (!f.match(/^server(-\d+)?\.json$/))
|
|
6604
|
+
continue;
|
|
6605
|
+
const filePath = join2(WASPER_DIR, f);
|
|
6606
|
+
try {
|
|
6607
|
+
const raw = await readFile(filePath, "utf-8");
|
|
6608
|
+
const state = JSON.parse(raw);
|
|
6609
|
+
if (isProcessAlive(state.pid)) {
|
|
6610
|
+
states.push(state);
|
|
6611
|
+
} else {
|
|
6612
|
+
await unlink(filePath).catch(() => {});
|
|
6613
|
+
}
|
|
6614
|
+
} catch {}
|
|
6615
|
+
}
|
|
6616
|
+
return states.sort((a, b) => a.port - b.port);
|
|
6596
6617
|
} catch {
|
|
6597
|
-
return
|
|
6618
|
+
return [];
|
|
6598
6619
|
}
|
|
6599
6620
|
}
|
|
6600
|
-
async function
|
|
6621
|
+
async function readDaemonState(port) {
|
|
6622
|
+
if (port !== undefined) {
|
|
6623
|
+
try {
|
|
6624
|
+
const raw = await readFile(stateFile(port), "utf-8");
|
|
6625
|
+
const state = JSON.parse(raw);
|
|
6626
|
+
return isProcessAlive(state.pid) ? state : null;
|
|
6627
|
+
} catch {
|
|
6628
|
+
return null;
|
|
6629
|
+
}
|
|
6630
|
+
}
|
|
6631
|
+
const all = await readAllDaemonStates();
|
|
6632
|
+
if (all.length === 0)
|
|
6633
|
+
return null;
|
|
6634
|
+
if (all.length === 1)
|
|
6635
|
+
return all[0];
|
|
6636
|
+
return all.find((s) => s.port === DEFAULT_PORT) ?? all[0];
|
|
6637
|
+
}
|
|
6638
|
+
async function clearDaemonState(port) {
|
|
6601
6639
|
try {
|
|
6602
|
-
await unlink(
|
|
6640
|
+
await unlink(stateFile(port));
|
|
6641
|
+
} catch {}
|
|
6642
|
+
try {
|
|
6643
|
+
const raw = await readFile(join2(WASPER_DIR, "server.json"), "utf-8");
|
|
6644
|
+
const state = JSON.parse(raw);
|
|
6645
|
+
if (state.port === port)
|
|
6646
|
+
await unlink(join2(WASPER_DIR, "server.json")).catch(() => {});
|
|
6603
6647
|
} catch {}
|
|
6604
6648
|
}
|
|
6605
6649
|
function isProcessAlive(pid) {
|
|
@@ -6633,22 +6677,19 @@ async function spawnDaemon(specUrl, port, opts = {}) {
|
|
|
6633
6677
|
args.push("--readonly");
|
|
6634
6678
|
}
|
|
6635
6679
|
args.push("--_daemon");
|
|
6636
|
-
const logDir = DIR;
|
|
6637
6680
|
await ensureDir();
|
|
6638
|
-
const logPath = join2(logDir, "server.log");
|
|
6639
6681
|
const child = Bun.spawn([process.execPath, Bun.main, ...args], {
|
|
6640
6682
|
detached: true,
|
|
6641
6683
|
cwd: process.cwd(),
|
|
6642
6684
|
env: { ...process.env },
|
|
6643
|
-
stdio: ["ignore", Bun.file(
|
|
6685
|
+
stdio: ["ignore", Bun.file(logFile(port)), Bun.file(logFile(port))]
|
|
6644
6686
|
});
|
|
6645
6687
|
child.unref();
|
|
6646
6688
|
return child.pid;
|
|
6647
6689
|
}
|
|
6648
|
-
var
|
|
6690
|
+
var WASPER_DIR, DEFAULT_PORT = 3388;
|
|
6649
6691
|
var init_daemon = __esm(() => {
|
|
6650
|
-
|
|
6651
|
-
STATE_FILE = join2(DIR, "server.json");
|
|
6692
|
+
WASPER_DIR = join2(homedir2(), ".wasper");
|
|
6652
6693
|
});
|
|
6653
6694
|
|
|
6654
6695
|
// src/ui.ts
|
|
@@ -7508,7 +7549,7 @@ async function run2(overrideOpts) {
|
|
|
7508
7549
|
${paint.dim("shutting down")}
|
|
7509
7550
|
|
|
7510
7551
|
`);
|
|
7511
|
-
clearDaemonState().finally(() => {
|
|
7552
|
+
clearDaemonState(PORT).finally(() => {
|
|
7512
7553
|
db.close();
|
|
7513
7554
|
server.stop();
|
|
7514
7555
|
process.exit(0);
|
|
@@ -7836,16 +7877,19 @@ function printInteractiveHelp() {
|
|
|
7836
7877
|
}
|
|
7837
7878
|
function printHelp() {
|
|
7838
7879
|
console.log(`
|
|
7839
|
-
Usage: wasper
|
|
7880
|
+
Usage: wasper start [options]
|
|
7881
|
+
|
|
7882
|
+
Starts wasper in the foreground with an interactive REPL.
|
|
7883
|
+
For background (daemon) mode \u2014 the default \u2014 use: wasper up
|
|
7840
7884
|
|
|
7841
|
-
wasper [--url <spec
|
|
7842
|
-
wasper start --
|
|
7843
|
-
wasper
|
|
7844
|
-
wasper status Show
|
|
7885
|
+
wasper up [--url <spec>] Start daemon in background (default)
|
|
7886
|
+
wasper start [--url <spec>] Start in foreground with REPL
|
|
7887
|
+
wasper down Stop the daemon
|
|
7888
|
+
wasper status Show daemon status
|
|
7889
|
+
wasper logs [-f] Tail server logs
|
|
7890
|
+
wasper service install Install as system service (auto-start)
|
|
7845
7891
|
wasper reload Hot-reload the spec
|
|
7846
7892
|
wasper ls List saved specs (history)
|
|
7847
|
-
wasper use <number|url> Start with a saved spec
|
|
7848
|
-
wasper rm <number|url> Remove a spec from history
|
|
7849
7893
|
|
|
7850
7894
|
Options:
|
|
7851
7895
|
--url, -u OpenAPI spec URL or local path
|
|
@@ -7860,17 +7904,17 @@ Options:
|
|
|
7860
7904
|
--no-proxy Start with the HTTP proxy disabled
|
|
7861
7905
|
--no-ai Start with the AI chat endpoint disabled
|
|
7862
7906
|
--readonly Block all non-GET upstream requests (agent guardrail)
|
|
7863
|
-
--background, -b Start detached in background
|
|
7907
|
+
--background, -b Start detached in background (same as wasper up)
|
|
7864
7908
|
--daemon, -d Same as --background
|
|
7865
7909
|
-h, --help Show this help
|
|
7866
7910
|
|
|
7867
|
-
Interactive
|
|
7911
|
+
Interactive REPL slash commands (foreground mode):
|
|
7868
7912
|
/mcp on|off \xB7 /proxy on|off \xB7 /ai on|off \xB7 /readonly on|off
|
|
7869
7913
|
/auth use <role> \xB7 /token new \xB7 /spec <url> \xB7 /tail \xB7 /help
|
|
7870
7914
|
|
|
7871
7915
|
Self-hosting:
|
|
7872
|
-
wasper
|
|
7873
|
-
|
|
7916
|
+
wasper up --url <spec> --origin https://api.example.com --token <secret>
|
|
7917
|
+
wasper service install --url <spec> --port 3388
|
|
7874
7918
|
`);
|
|
7875
7919
|
}
|
|
7876
7920
|
function buildScalarHtml(title, req) {
|