@suronai/cli 0.1.11 → 0.1.12
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/package.json +6 -12
- package/src/commands/init.js +131 -0
- package/src/commands/login.js +56 -0
- package/src/commands/rotate.js +79 -0
- package/src/commands/whoami.js +13 -0
- package/src/index.js +21 -0
- package/src/utils/colors.js +11 -0
- package/src/utils/config.js +67 -0
- package/src/utils/dotenvx.js +58 -0
- package/dist/commands/init.d.ts +0 -2
- package/dist/commands/init.js +0 -127
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/login.d.ts +0 -2
- package/dist/commands/login.js +0 -56
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/rotate.d.ts +0 -2
- package/dist/commands/rotate.js +0 -73
- package/dist/commands/rotate.js.map +0 -1
- package/dist/commands/set-telegram.d.ts +0 -0
- package/dist/commands/set-telegram.js +0 -3
- package/dist/commands/set-telegram.js.map +0 -1
- package/dist/commands/whoami.d.ts +0 -2
- package/dist/commands/whoami.js +0 -13
- package/dist/commands/whoami.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -19
- package/dist/index.js.map +0 -1
- package/dist/utils/config.d.ts +0 -12
- package/dist/utils/config.js +0 -117
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/dotenvx.d.ts +0 -14
- package/dist/utils/dotenvx.js +0 -47
- package/dist/utils/dotenvx.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,28 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suronai/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "CLI for Suron — suron login, init, whoami, rotate",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"bin": {
|
|
6
|
-
"suron": "./
|
|
7
|
+
"suron": "./src/index.js"
|
|
7
8
|
},
|
|
8
9
|
"files": [
|
|
9
|
-
"
|
|
10
|
+
"src"
|
|
10
11
|
],
|
|
11
12
|
"scripts": {
|
|
12
|
-
"build": "node
|
|
13
|
-
"
|
|
14
|
-
"clean": "rimraf dist"
|
|
13
|
+
"build": "node --check src/index.js src/commands/login.js src/commands/init.js src/commands/rotate.js src/commands/whoami.js src/utils/config.js src/utils/dotenvx.js src/utils/colors.js",
|
|
14
|
+
"lint": "node --check src/index.js src/commands/login.js src/commands/init.js src/commands/rotate.js src/commands/whoami.js src/utils/config.js src/utils/dotenvx.js src/utils/colors.js"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@dotenvx/dotenvx": "^1.0.0",
|
|
18
|
-
"chalk": "^5.3.0",
|
|
19
18
|
"commander": "^12.0.0"
|
|
20
19
|
},
|
|
21
|
-
"devDependencies": {
|
|
22
|
-
"@types/node": "^20.0.0",
|
|
23
|
-
"rimraf": "^5.0.0",
|
|
24
|
-
"typescript": "^5.9.3"
|
|
25
|
-
},
|
|
26
20
|
"engines": {
|
|
27
21
|
"node": ">=18.0.0"
|
|
28
22
|
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { existsSync, writeFileSync, readFileSync } from "fs";
|
|
3
|
+
import { join, basename } from "path";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import { requireApiUrl, prompt } from "../utils/config.js";
|
|
6
|
+
import { encryptDotenv, readPrivateKey, deleteKeysFile } from "../utils/dotenvx.js";
|
|
7
|
+
import c from "../utils/colors.js";
|
|
8
|
+
|
|
9
|
+
export const initCommand = new Command("init")
|
|
10
|
+
.description("Encrypt .env and register this app with Suron")
|
|
11
|
+
.option("--name <n>", "App name (skips interactive prompt)")
|
|
12
|
+
.action(async (opts) => {
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const apiUrl = requireApiUrl();
|
|
15
|
+
|
|
16
|
+
console.log("\n" + c.bold(" suron init") + " — " + c.dim(cwd) + "\n");
|
|
17
|
+
|
|
18
|
+
if (!existsSync(join(cwd, ".env"))) {
|
|
19
|
+
console.error(" " + c.red("✗") + " .env not found in current directory");
|
|
20
|
+
console.error(" Create a .env file with your secrets, then run: suron init\n");
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ── App name ─────────────────────────────────────────────────────────────
|
|
25
|
+
const suggested = basename(cwd) || "my-project";
|
|
26
|
+
let appName;
|
|
27
|
+
|
|
28
|
+
if (opts.name) {
|
|
29
|
+
appName = opts.name;
|
|
30
|
+
console.log(" App name " + c.cyan(appName));
|
|
31
|
+
} else {
|
|
32
|
+
const input = await prompt(` App name [${c.dim(suggested)}] › `);
|
|
33
|
+
appName = input || suggested;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ── Encrypt ───────────────────────────────────────────────────────────────
|
|
37
|
+
console.log("\n " + c.dim("Encrypting .env..."));
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
encryptDotenv(cwd);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.error("\n " + c.red("✗") + " " + err.message + "\n");
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let privateKey;
|
|
47
|
+
try {
|
|
48
|
+
privateKey = readPrivateKey(cwd);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.error("\n " + c.red("✗") + " " + err.message + "\n");
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ── Register ──────────────────────────────────────────────────────────────
|
|
55
|
+
console.log(" " + c.dim("Registering app..."));
|
|
56
|
+
|
|
57
|
+
let res;
|
|
58
|
+
try {
|
|
59
|
+
res = await fetch(`${apiUrl}/cli/register-app`, {
|
|
60
|
+
method: "POST",
|
|
61
|
+
headers: { "Content-Type": "application/json" },
|
|
62
|
+
body: JSON.stringify({ name: appName, private_key: privateKey }),
|
|
63
|
+
});
|
|
64
|
+
} catch (err) {
|
|
65
|
+
console.error("\n " + c.red("✗") + ` Could not reach Suron API: ${err.message}\n`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!res.ok) {
|
|
70
|
+
const text = await res.text().catch(() => "");
|
|
71
|
+
console.error("\n " + c.red("✗") + ` register-app failed (${res.status}): ${text}\n`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { app_id } = await res.json();
|
|
76
|
+
|
|
77
|
+
// ── Write .suron.json + clean up ──────────────────────────────────────────
|
|
78
|
+
deleteKeysFile(cwd);
|
|
79
|
+
|
|
80
|
+
writeFileSync(
|
|
81
|
+
join(cwd, ".suron.json"),
|
|
82
|
+
JSON.stringify({ app: appName, id: app_id, api_url: apiUrl }, null, 2) + "\n",
|
|
83
|
+
"utf-8"
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
// ── Install SDK ───────────────────────────────────────────────────────────
|
|
87
|
+
const pkgJsonPath = join(cwd, "package.json");
|
|
88
|
+
|
|
89
|
+
if (existsSync(pkgJsonPath)) {
|
|
90
|
+
let alreadyInstalled = false;
|
|
91
|
+
try {
|
|
92
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
93
|
+
alreadyInstalled = !!(pkg.dependencies?.["@suronai/sdk"] || pkg.devDependencies?.["@suronai/sdk"]);
|
|
94
|
+
} catch { /* ignore */ }
|
|
95
|
+
|
|
96
|
+
if (!alreadyInstalled) {
|
|
97
|
+
console.log(" " + c.dim("Installing @suronai/sdk..."));
|
|
98
|
+
const pm = detectPackageManager(cwd);
|
|
99
|
+
try {
|
|
100
|
+
execSync(`${pm} ${pmAddCmd(pm)} @suronai/sdk`, { cwd, stdio: "inherit" });
|
|
101
|
+
} catch {
|
|
102
|
+
console.error(" " + c.yellow("⚠") + " SDK install failed — run manually: npm install @suronai/sdk");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ── Done ──────────────────────────────────────────────────────────────────
|
|
108
|
+
console.log();
|
|
109
|
+
console.log(" " + c.green("✓") + " .env encrypted " + c.dim("(safe to commit)"));
|
|
110
|
+
console.log(" " + c.green("✓") + " .env.keys deleted");
|
|
111
|
+
console.log(" " + c.green("✓") + " .suron.json written " + c.dim("(safe to commit)"));
|
|
112
|
+
console.log(" " + c.green("✓") + " @suronai/sdk installed");
|
|
113
|
+
console.log();
|
|
114
|
+
console.log(" Add to your app entry point:\n");
|
|
115
|
+
console.log(" " + c.cyan("import") + " { vault } from " + c.green("'@suronai/sdk'"));
|
|
116
|
+
console.log(" " + c.cyan("await") + " vault()");
|
|
117
|
+
console.log();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
/** @param {string} cwd @returns {string} */
|
|
121
|
+
function detectPackageManager(cwd) {
|
|
122
|
+
if (existsSync(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
123
|
+
if (existsSync(join(cwd, "yarn.lock"))) return "yarn";
|
|
124
|
+
if (existsSync(join(cwd, "bun.lockb"))) return "bun";
|
|
125
|
+
return "npm";
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** @param {string} pm @returns {string} */
|
|
129
|
+
function pmAddCmd(pm) {
|
|
130
|
+
return pm === "npm" ? "install" : "add";
|
|
131
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { getApiUrl, saveConfig, prompt } from "../utils/config.js";
|
|
3
|
+
import c from "../utils/colors.js";
|
|
4
|
+
|
|
5
|
+
export const loginCommand = new Command("login")
|
|
6
|
+
.description("Configure the Suron API URL")
|
|
7
|
+
.action(async () => {
|
|
8
|
+
console.log("\n" + c.bold(" Suron") + " — configure your backend\n");
|
|
9
|
+
|
|
10
|
+
let apiUrl = getApiUrl();
|
|
11
|
+
|
|
12
|
+
if (apiUrl) {
|
|
13
|
+
console.log(" Current URL " + c.cyan(apiUrl));
|
|
14
|
+
const change = await prompt(" Change it? (y/N) › ");
|
|
15
|
+
if (change.toLowerCase() !== "y") {
|
|
16
|
+
console.log("\n " + c.green("✓") + " No changes made.\n");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const input = await prompt(" Convex deployment URL › ");
|
|
22
|
+
if (!input) {
|
|
23
|
+
console.error("\n " + c.red("✗") + " URL is required.\n");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
apiUrl = input.replace(/\/$/, "");
|
|
27
|
+
|
|
28
|
+
process.stdout.write("\n Verifying connection...");
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const res = await fetch(`${apiUrl}/cli/verify`, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
headers: { "Content-Type": "application/json" },
|
|
34
|
+
body: JSON.stringify({}),
|
|
35
|
+
});
|
|
36
|
+
if (!res.ok) {
|
|
37
|
+
const text = await res.text().catch(() => "");
|
|
38
|
+
process.stdout.write("\r" + " ".repeat(30) + "\r");
|
|
39
|
+
console.error(" " + c.red("✗") + ` Backend returned ${res.status}: ${text}\n`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
process.stdout.write("\r" + " ".repeat(30) + "\r");
|
|
44
|
+
console.error(" " + c.red("✗") + ` Could not reach ${c.cyan(apiUrl)}`);
|
|
45
|
+
console.error(" Is the Convex deployment running?\n");
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
process.stdout.write("\r" + " ".repeat(30) + "\r");
|
|
50
|
+
|
|
51
|
+
saveConfig({ apiUrl });
|
|
52
|
+
|
|
53
|
+
console.log(" " + c.green("✓") + " Connected");
|
|
54
|
+
console.log(" " + c.green("✓") + " Saved to ~/.suron-config");
|
|
55
|
+
console.log("\n Next: cd your-project && " + c.bold("suron init") + "\n");
|
|
56
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { existsSync, readFileSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { requireApiUrl } from "../utils/config.js";
|
|
5
|
+
import { encryptDotenv, readPrivateKey, deleteKeysFile } from "../utils/dotenvx.js";
|
|
6
|
+
import c from "../utils/colors.js";
|
|
7
|
+
|
|
8
|
+
export const rotateCommand = new Command("rotate")
|
|
9
|
+
.description("Re-encrypt .env with a new private key and update Suron")
|
|
10
|
+
.action(async () => {
|
|
11
|
+
const cwd = process.cwd();
|
|
12
|
+
const apiUrl = requireApiUrl();
|
|
13
|
+
|
|
14
|
+
console.log("\n" + c.bold(" suron rotate") + " — " + c.dim(cwd) + "\n");
|
|
15
|
+
|
|
16
|
+
const suronJsonPath = join(cwd, ".suron.json");
|
|
17
|
+
if (!existsSync(suronJsonPath)) {
|
|
18
|
+
console.error(" " + c.red("✗") + " .suron.json not found — run: suron init\n");
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let suronConfig;
|
|
23
|
+
try {
|
|
24
|
+
suronConfig = JSON.parse(readFileSync(suronJsonPath, "utf-8"));
|
|
25
|
+
} catch {
|
|
26
|
+
console.error(" " + c.red("✗") + " .suron.json is malformed\n");
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!existsSync(join(cwd, ".env"))) {
|
|
31
|
+
console.error(" " + c.red("✗") + " .env not found\n");
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.log(" " + c.dim("Re-encrypting .env with a new private key..."));
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
encryptDotenv(cwd);
|
|
39
|
+
} catch (err) {
|
|
40
|
+
console.error("\n " + c.red("✗") + " " + err.message + "\n");
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let newPrivateKey;
|
|
45
|
+
try {
|
|
46
|
+
newPrivateKey = readPrivateKey(cwd);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.error("\n " + c.red("✗") + " " + err.message + "\n");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log(" " + c.dim("Updating private key in Suron..."));
|
|
53
|
+
|
|
54
|
+
let res;
|
|
55
|
+
try {
|
|
56
|
+
res = await fetch(`${apiUrl}/cli/rotate-key`, {
|
|
57
|
+
method: "POST",
|
|
58
|
+
headers: { "Content-Type": "application/json" },
|
|
59
|
+
body: JSON.stringify({ app_id: suronConfig.id, private_key: newPrivateKey }),
|
|
60
|
+
});
|
|
61
|
+
} catch (err) {
|
|
62
|
+
console.error("\n " + c.red("✗") + ` Could not reach Suron API: ${err.message}\n`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!res.ok) {
|
|
67
|
+
const text = await res.text().catch(() => "");
|
|
68
|
+
console.error("\n " + c.red("✗") + ` rotate-key failed (${res.status}): ${text}\n`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
deleteKeysFile(cwd);
|
|
73
|
+
|
|
74
|
+
console.log();
|
|
75
|
+
console.log(" " + c.green("✓") + " Key rotated");
|
|
76
|
+
console.log(" " + c.green("✓") + " .env re-encrypted " + c.dim("(safe to commit)"));
|
|
77
|
+
console.log(" " + c.green("✓") + " .env.keys deleted");
|
|
78
|
+
console.log();
|
|
79
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { requireApiUrl } from "../utils/config.js";
|
|
3
|
+
import c from "../utils/colors.js";
|
|
4
|
+
|
|
5
|
+
export const whoamiCommand = new Command("whoami")
|
|
6
|
+
.description("Show configured Suron API URL")
|
|
7
|
+
.action(() => {
|
|
8
|
+
const apiUrl = requireApiUrl();
|
|
9
|
+
console.log();
|
|
10
|
+
console.log(" " + c.bold("API URL") + " " + c.cyan(apiUrl));
|
|
11
|
+
console.log(" " + c.bold("Config file") + " ~/.suron-config");
|
|
12
|
+
console.log();
|
|
13
|
+
});
|
package/src/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { loginCommand } from "./commands/login.js";
|
|
5
|
+
import { initCommand } from "./commands/init.js";
|
|
6
|
+
import { whoamiCommand } from "./commands/whoami.js";
|
|
7
|
+
import { rotateCommand } from "./commands/rotate.js";
|
|
8
|
+
|
|
9
|
+
const program = new Command();
|
|
10
|
+
|
|
11
|
+
program
|
|
12
|
+
.name("suron")
|
|
13
|
+
.description("Secrets delivery with Telegram approval")
|
|
14
|
+
.version("0.1.11");
|
|
15
|
+
|
|
16
|
+
program.addCommand(loginCommand);
|
|
17
|
+
program.addCommand(initCommand);
|
|
18
|
+
program.addCommand(whoamiCommand);
|
|
19
|
+
program.addCommand(rotateCommand);
|
|
20
|
+
|
|
21
|
+
program.parse(process.argv);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Minimal ANSI helpers — no deps, works in any Node.js
|
|
2
|
+
export const c = {
|
|
3
|
+
bold: (s) => `\x1b[1m${s}\x1b[0m`,
|
|
4
|
+
dim: (s) => `\x1b[2m${s}\x1b[0m`,
|
|
5
|
+
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
6
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
7
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
8
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default c;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { homedir } from "os";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
4
|
+
import readline from "readline";
|
|
5
|
+
import c from "./colors.js";
|
|
6
|
+
|
|
7
|
+
const CONFIG_PATH = join(homedir(), ".suron-config");
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @returns {{ apiUrl?: string }}
|
|
11
|
+
*/
|
|
12
|
+
export function readConfig() {
|
|
13
|
+
if (!existsSync(CONFIG_PATH)) return {};
|
|
14
|
+
try {
|
|
15
|
+
const config = {};
|
|
16
|
+
for (const line of readFileSync(CONFIG_PATH, "utf-8").split("\n")) {
|
|
17
|
+
const eq = line.indexOf("=");
|
|
18
|
+
if (eq === -1) continue;
|
|
19
|
+
const key = line.slice(0, eq).trim();
|
|
20
|
+
const val = line.slice(eq + 1).trim();
|
|
21
|
+
if (!val) continue;
|
|
22
|
+
if (key === "SURON_API_URL") config.apiUrl = val;
|
|
23
|
+
}
|
|
24
|
+
return config;
|
|
25
|
+
} catch {
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {{ apiUrl?: string }} values
|
|
32
|
+
*/
|
|
33
|
+
export function saveConfig(values) {
|
|
34
|
+
const merged = { ...readConfig(), ...values };
|
|
35
|
+
const lines = [];
|
|
36
|
+
if (merged.apiUrl) lines.push(`SURON_API_URL=${merged.apiUrl}`);
|
|
37
|
+
writeFileSync(CONFIG_PATH, lines.join("\n") + "\n", { mode: 0o600 });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** @returns {string | null} */
|
|
41
|
+
export function getApiUrl() {
|
|
42
|
+
return process.env.SURON_API_URL?.replace(/\/$/, "") ?? readConfig().apiUrl ?? null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** @returns {string} */
|
|
46
|
+
export function requireApiUrl() {
|
|
47
|
+
const url = getApiUrl();
|
|
48
|
+
if (!url) {
|
|
49
|
+
console.error(c.red(" error:") + " not configured. Run: suron login");
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
return url;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {string} question
|
|
57
|
+
* @returns {Promise<string>}
|
|
58
|
+
*/
|
|
59
|
+
export function prompt(question) {
|
|
60
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
61
|
+
return new Promise((resolve) => {
|
|
62
|
+
rl.question(question, (answer) => {
|
|
63
|
+
rl.close();
|
|
64
|
+
resolve(answer.trim());
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import { existsSync, readFileSync, unlinkSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Encrypts .env in-place using dotenvx.
|
|
7
|
+
* On success: .env is encrypted, .env.keys contains the private key.
|
|
8
|
+
* If dotenvx exits 0 but .env.keys doesn't exist, the file was already
|
|
9
|
+
* encrypted — readPrivateKey() will throw a clear error explaining that.
|
|
10
|
+
* @param {string} cwd
|
|
11
|
+
*/
|
|
12
|
+
export function encryptDotenv(cwd) {
|
|
13
|
+
if (!existsSync(join(cwd, ".env"))) {
|
|
14
|
+
throw new Error(`.env not found in ${cwd}`);
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const output = execSync("npx @dotenvx/dotenvx encrypt", {
|
|
18
|
+
cwd,
|
|
19
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
20
|
+
}).toString();
|
|
21
|
+
if (output) process.stdout.write(output);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
const stderr = err.stderr?.toString() ?? "";
|
|
24
|
+
const stdout = err.stdout?.toString() ?? "";
|
|
25
|
+
if (stdout) process.stdout.write(stdout);
|
|
26
|
+
throw new Error(`dotenvx encrypt failed: ${stderr || err}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Reads the private key out of .env.keys after encryption.
|
|
32
|
+
* @param {string} cwd
|
|
33
|
+
* @returns {string}
|
|
34
|
+
*/
|
|
35
|
+
export function readPrivateKey(cwd) {
|
|
36
|
+
const keysPath = join(cwd, ".env.keys");
|
|
37
|
+
if (!existsSync(keysPath)) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
".env.keys not found after encryption.\n" +
|
|
40
|
+
" Your .env may already be encrypted — restore plaintext values and run: suron init"
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const content = readFileSync(keysPath, "utf-8");
|
|
44
|
+
const match = content.match(/DOTENV_PRIVATE_KEY(?:_\w+)?="?([^"\n]+)"?/);
|
|
45
|
+
if (!match?.[1]) {
|
|
46
|
+
throw new Error("Could not parse DOTENV_PRIVATE_KEY from .env.keys");
|
|
47
|
+
}
|
|
48
|
+
return match[1].trim();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Deletes .env.keys after the private key has been stored in Convex.
|
|
53
|
+
* @param {string} cwd
|
|
54
|
+
*/
|
|
55
|
+
export function deleteKeysFile(cwd) {
|
|
56
|
+
const keysPath = join(cwd, ".env.keys");
|
|
57
|
+
if (existsSync(keysPath)) unlinkSync(keysPath);
|
|
58
|
+
}
|
package/dist/commands/init.d.ts
DELETED
package/dist/commands/init.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.initCommand = void 0;
|
|
4
|
-
const commander_1 = require("commander");
|
|
5
|
-
const fs_1 = require("fs");
|
|
6
|
-
const path_1 = require("path");
|
|
7
|
-
const child_process_1 = require("child_process");
|
|
8
|
-
const config_1 = require("../utils/config");
|
|
9
|
-
const dotenvx_1 = require("../utils/dotenvx");
|
|
10
|
-
exports.initCommand = new commander_1.Command("init")
|
|
11
|
-
.description("Encrypt .env and register this app with Suron")
|
|
12
|
-
.option("--app <name>", "App name (skips interactive prompt)")
|
|
13
|
-
.action(async (opts) => {
|
|
14
|
-
const cwd = process.cwd();
|
|
15
|
-
const apiUrl = (0, config_1.requireApiUrl)();
|
|
16
|
-
if (!(0, fs_1.existsSync)((0, path_1.join)(cwd, ".env"))) {
|
|
17
|
-
console.error("error: .env not found in current directory");
|
|
18
|
-
console.error(" Create a .env file first, then run: suron init");
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
21
|
-
const suggested = require("path").basename(cwd) || "my-project";
|
|
22
|
-
let appName;
|
|
23
|
-
if (opts.app) {
|
|
24
|
-
appName = opts.app;
|
|
25
|
-
console.log(`[suron] App name: ${appName}`);
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
const input = await (0, config_1.prompt)(` App name [${suggested}]: `);
|
|
29
|
-
appName = input.trim() || suggested;
|
|
30
|
-
}
|
|
31
|
-
console.log(`[suron] Encrypting .env with dotenvx...`);
|
|
32
|
-
try {
|
|
33
|
-
(0, dotenvx_1.encryptDotenv)(cwd);
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
console.error(`error: dotenvx encryption failed: ${err}`);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
let privateKey;
|
|
40
|
-
try {
|
|
41
|
-
privateKey = (0, dotenvx_1.readPrivateKey)(cwd);
|
|
42
|
-
}
|
|
43
|
-
catch (err) {
|
|
44
|
-
console.error(`error: ${err}`);
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
console.log("[suron] Registering app...");
|
|
48
|
-
let res;
|
|
49
|
-
try {
|
|
50
|
-
res = await fetch(`${apiUrl}/cli/register-app`, {
|
|
51
|
-
method: "POST",
|
|
52
|
-
headers: { "Content-Type": "application/json" },
|
|
53
|
-
body: JSON.stringify({
|
|
54
|
-
name: appName,
|
|
55
|
-
private_key: privateKey,
|
|
56
|
-
}),
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
catch (err) {
|
|
60
|
-
console.error(`error: could not reach Suron API: ${err}`);
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
if (!res.ok) {
|
|
64
|
-
const text = await res.text().catch(() => "");
|
|
65
|
-
console.error(`error: register-app failed (${res.status}): ${text}`);
|
|
66
|
-
process.exit(1);
|
|
67
|
-
}
|
|
68
|
-
const data = (await res.json());
|
|
69
|
-
(0, dotenvx_1.deleteKeysFile)(cwd);
|
|
70
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(cwd, ".suron.json"), JSON.stringify({ app: appName, id: data.app_id, api_url: apiUrl }, null, 2) + "\n", "utf-8");
|
|
71
|
-
// Install @suronai/sdk into the project
|
|
72
|
-
const pkgJsonPath = (0, path_1.join)(cwd, "package.json");
|
|
73
|
-
if ((0, fs_1.existsSync)(pkgJsonPath)) {
|
|
74
|
-
let alreadyInstalled = false;
|
|
75
|
-
try {
|
|
76
|
-
const pkg = JSON.parse((0, fs_1.readFileSync)(pkgJsonPath, "utf-8"));
|
|
77
|
-
alreadyInstalled = !!(pkg.dependencies?.["@suronai/sdk"] ||
|
|
78
|
-
pkg.devDependencies?.["@suronai/sdk"]);
|
|
79
|
-
}
|
|
80
|
-
catch { /* ignore parse errors */ }
|
|
81
|
-
if (alreadyInstalled) {
|
|
82
|
-
console.log("[suron] @suronai/sdk already in package.json, skipping install");
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
console.log("[suron] Installing @suronai/sdk...");
|
|
86
|
-
const pm = detectPackageManager(cwd);
|
|
87
|
-
try {
|
|
88
|
-
(0, child_process_1.execSync)(`${pm} ${pmAddCmd(pm)} @suronai/sdk`, { cwd, stdio: "inherit" });
|
|
89
|
-
}
|
|
90
|
-
catch (err) {
|
|
91
|
-
console.error(`error: failed to install @suronai/sdk: ${err}`);
|
|
92
|
-
console.error(` Run manually: npm install @suronai/sdk`);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
console.log("[suron] No package.json found — skipping SDK install");
|
|
98
|
-
console.log(" Run manually: npm install @suronai/sdk");
|
|
99
|
-
}
|
|
100
|
-
console.log(`[suron] Done.`);
|
|
101
|
-
console.log(` .env is encrypted — safe to commit`);
|
|
102
|
-
console.log(` .env.keys deleted`);
|
|
103
|
-
console.log(` .suron.json written — safe to commit`);
|
|
104
|
-
console.log(` @suronai/sdk installed`);
|
|
105
|
-
console.log(`\n Next: add to your app entry point:`);
|
|
106
|
-
console.log(` import { vault } from '@suronai/sdk'`);
|
|
107
|
-
console.log(` await vault()\n`);
|
|
108
|
-
});
|
|
109
|
-
function detectPackageManager(cwd) {
|
|
110
|
-
if ((0, fs_1.existsSync)((0, path_1.join)(cwd, "pnpm-lock.yaml")))
|
|
111
|
-
return "pnpm";
|
|
112
|
-
if ((0, fs_1.existsSync)((0, path_1.join)(cwd, "yarn.lock")))
|
|
113
|
-
return "yarn";
|
|
114
|
-
if ((0, fs_1.existsSync)((0, path_1.join)(cwd, "bun.lockb")))
|
|
115
|
-
return "bun";
|
|
116
|
-
return "npm";
|
|
117
|
-
}
|
|
118
|
-
function pmAddCmd(pm) {
|
|
119
|
-
if (pm === "yarn")
|
|
120
|
-
return "add";
|
|
121
|
-
if (pm === "pnpm")
|
|
122
|
-
return "add";
|
|
123
|
-
if (pm === "bun")
|
|
124
|
-
return "add";
|
|
125
|
-
return "install";
|
|
126
|
-
}
|
|
127
|
-
//# sourceMappingURL=init.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/login.d.ts
DELETED
package/dist/commands/login.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loginCommand = void 0;
|
|
4
|
-
const commander_1 = require("commander");
|
|
5
|
-
const config_1 = require("../utils/config");
|
|
6
|
-
exports.loginCommand = new commander_1.Command("login")
|
|
7
|
-
.description("Configure the Suron API URL")
|
|
8
|
-
.action(async () => {
|
|
9
|
-
console.log("\n Suron Setup\n");
|
|
10
|
-
let apiUrl = (0, config_1.getApiUrl)();
|
|
11
|
-
if (!apiUrl) {
|
|
12
|
-
const input = await (0, config_1.prompt)(" Convex deployment URL (https://xxx.convex.site): ");
|
|
13
|
-
if (!input) {
|
|
14
|
-
console.error("\nerror: URL is required");
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
17
|
-
apiUrl = input.replace(/\/$/, "");
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
console.log(` Convex URL: ${apiUrl}`);
|
|
21
|
-
const change = await (0, config_1.prompt)(" Change it? (y/N): ");
|
|
22
|
-
if (change.toLowerCase() === "y") {
|
|
23
|
-
const input = await (0, config_1.prompt)(" New URL: ");
|
|
24
|
-
if (!input) {
|
|
25
|
-
console.error("\nerror: URL required");
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
apiUrl = input.replace(/\/$/, "");
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
// Verify the backend is reachable
|
|
32
|
-
console.log("\n Verifying connection...");
|
|
33
|
-
try {
|
|
34
|
-
const res = await fetch(`${apiUrl}/cli/verify`, {
|
|
35
|
-
method: "POST",
|
|
36
|
-
headers: { "Content-Type": "application/json" },
|
|
37
|
-
body: JSON.stringify({}),
|
|
38
|
-
});
|
|
39
|
-
// A 400 (missing telegram_id) means the route exists and backend is up
|
|
40
|
-
if (!res.ok && res.status !== 400) {
|
|
41
|
-
const text = await res.text().catch(() => "");
|
|
42
|
-
console.error(`\nerror: backend returned (${res.status}): ${text}`);
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
catch (err) {
|
|
47
|
-
console.error(`\nerror: could not reach ${apiUrl}`);
|
|
48
|
-
console.error(` Is the Convex deployment running?`);
|
|
49
|
-
process.exit(1);
|
|
50
|
-
}
|
|
51
|
-
(0, config_1.saveConfig)({ apiUrl });
|
|
52
|
-
console.log("\n Saved to ~/.suron-config");
|
|
53
|
-
console.log(" Setup complete.\n");
|
|
54
|
-
console.log(" Next: cd your-project && suron init\n");
|
|
55
|
-
});
|
|
56
|
-
//# sourceMappingURL=login.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,4CAAgE;AAEnD,QAAA,YAAY,GAAG,IAAI,mBAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAEjC,IAAI,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;IACzB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,KAAK,GAAG,MAAM,IAAA,eAAM,EAAC,qDAAqD,CAAC,CAAC;QAClF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,IAAA,eAAM,EAAC,sBAAsB,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,MAAM,IAAA,eAAM,EAAC,aAAa,CAAC,CAAC;YAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;gBAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;YACxE,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,aAAa,EAAE;YAC9C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;SACzB,CAAC,CAAC;QACH,uEAAuE;QACvE,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,OAAO,CAAC,KAAK,CAAC,8BAA8B,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,MAAM,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAA,mBAAU,EAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC"}
|
package/dist/commands/rotate.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.rotateCommand = void 0;
|
|
4
|
-
const commander_1 = require("commander");
|
|
5
|
-
const fs_1 = require("fs");
|
|
6
|
-
const path_1 = require("path");
|
|
7
|
-
const config_1 = require("../utils/config");
|
|
8
|
-
const dotenvx_1 = require("../utils/dotenvx");
|
|
9
|
-
exports.rotateCommand = new commander_1.Command("rotate")
|
|
10
|
-
.description("Re-encrypt .env with a new private key and update Suron")
|
|
11
|
-
.action(async () => {
|
|
12
|
-
const cwd = process.cwd();
|
|
13
|
-
const apiUrl = (0, config_1.requireApiUrl)();
|
|
14
|
-
const suronJsonPath = (0, path_1.join)(cwd, ".suron.json");
|
|
15
|
-
if (!(0, fs_1.existsSync)(suronJsonPath)) {
|
|
16
|
-
console.error("error: .suron.json not found. Run: suron init first");
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
let suronConfig;
|
|
20
|
-
try {
|
|
21
|
-
suronConfig = JSON.parse((0, fs_1.readFileSync)(suronJsonPath, "utf-8"));
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
console.error("error: .suron.json is malformed");
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
27
|
-
if (!(0, fs_1.existsSync)((0, path_1.join)(cwd, ".env"))) {
|
|
28
|
-
console.error("error: .env not found");
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
console.log("[suron] Re-encrypting .env with a new private key...");
|
|
32
|
-
try {
|
|
33
|
-
(0, dotenvx_1.encryptDotenv)(cwd);
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
console.error(`error: dotenvx encryption failed: ${err}`);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
let newPrivateKey;
|
|
40
|
-
try {
|
|
41
|
-
newPrivateKey = (0, dotenvx_1.readPrivateKey)(cwd);
|
|
42
|
-
}
|
|
43
|
-
catch (err) {
|
|
44
|
-
console.error(`error: ${err}`);
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
console.log("[suron] Updating private key in Suron...");
|
|
48
|
-
let res;
|
|
49
|
-
try {
|
|
50
|
-
res = await fetch(`${apiUrl}/cli/rotate-key`, {
|
|
51
|
-
method: "POST",
|
|
52
|
-
headers: { "Content-Type": "application/json" },
|
|
53
|
-
body: JSON.stringify({
|
|
54
|
-
app_id: suronConfig.id,
|
|
55
|
-
private_key: newPrivateKey,
|
|
56
|
-
}),
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
catch (err) {
|
|
60
|
-
console.error(`error: could not reach Suron API: ${err}`);
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
if (!res.ok) {
|
|
64
|
-
const text = await res.text().catch(() => "");
|
|
65
|
-
console.error(`error: rotate-key failed (${res.status}): ${text}`);
|
|
66
|
-
process.exit(1);
|
|
67
|
-
}
|
|
68
|
-
(0, dotenvx_1.deleteKeysFile)(cwd);
|
|
69
|
-
console.log("[suron] Key rotated.");
|
|
70
|
-
console.log(" .env re-encrypted — safe to commit");
|
|
71
|
-
console.log(" .env.keys deleted");
|
|
72
|
-
});
|
|
73
|
-
//# sourceMappingURL=rotate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rotate.js","sourceRoot":"","sources":["../../src/commands/rotate.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set-telegram.js","sourceRoot":"","sources":["../../src/commands/set-telegram.ts"],"names":[],"mappings":";AAAA,UAAU"}
|
package/dist/commands/whoami.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.whoamiCommand = void 0;
|
|
4
|
-
const commander_1 = require("commander");
|
|
5
|
-
const config_1 = require("../utils/config");
|
|
6
|
-
exports.whoamiCommand = new commander_1.Command("whoami")
|
|
7
|
-
.description("Show your configured account info")
|
|
8
|
-
.action(async () => {
|
|
9
|
-
const apiUrl = (0, config_1.requireApiUrl)();
|
|
10
|
-
console.log(`api url: ${apiUrl}`);
|
|
11
|
-
console.log(`config file: ~/.suron-config`);
|
|
12
|
-
});
|
|
13
|
-
//# sourceMappingURL=whoami.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,4CAAgD;AAEnC,QAAA,aAAa,GAAG,IAAI,mBAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,mCAAmC,CAAC;KAChD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,MAAM,GAAG,IAAA,sBAAa,GAAE,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;AAC9C,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
DELETED
package/dist/index.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
const commander_1 = require("commander");
|
|
5
|
-
const login_1 = require("./commands/login");
|
|
6
|
-
const init_1 = require("./commands/init");
|
|
7
|
-
const whoami_1 = require("./commands/whoami");
|
|
8
|
-
const rotate_1 = require("./commands/rotate");
|
|
9
|
-
const program = new commander_1.Command();
|
|
10
|
-
program
|
|
11
|
-
.name("suron")
|
|
12
|
-
.description("Secrets delivery with Telegram approval")
|
|
13
|
-
.version("0.1.0");
|
|
14
|
-
program.addCommand(login_1.loginCommand);
|
|
15
|
-
program.addCommand(init_1.initCommand);
|
|
16
|
-
program.addCommand(whoami_1.whoamiCommand);
|
|
17
|
-
program.addCommand(rotate_1.rotateCommand);
|
|
18
|
-
program.parse(process.argv);
|
|
19
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,4CAAgD;AAChD,0CAA8C;AAC9C,8CAAkD;AAClD,8CAAkD;AAElD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,yCAAyC,CAAC;KACtD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,oBAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,kBAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
package/dist/utils/config.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
interface Config {
|
|
2
|
-
apiUrl?: string;
|
|
3
|
-
apiKey?: string;
|
|
4
|
-
}
|
|
5
|
-
export declare function saveConfig(values: Partial<Config>): void;
|
|
6
|
-
export declare function getApiUrl(): string | null;
|
|
7
|
-
export declare function getApiKey(): string | null;
|
|
8
|
-
export declare function saveApiKey(key: string): void;
|
|
9
|
-
export declare function requireApiUrl(): string;
|
|
10
|
-
export declare function requireApiKey(): string;
|
|
11
|
-
export declare function prompt(question: string): Promise<string>;
|
|
12
|
-
export {};
|
package/dist/utils/config.js
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.saveConfig = saveConfig;
|
|
37
|
-
exports.getApiUrl = getApiUrl;
|
|
38
|
-
exports.getApiKey = getApiKey;
|
|
39
|
-
exports.saveApiKey = saveApiKey;
|
|
40
|
-
exports.requireApiUrl = requireApiUrl;
|
|
41
|
-
exports.requireApiKey = requireApiKey;
|
|
42
|
-
exports.prompt = prompt;
|
|
43
|
-
const os_1 = require("os");
|
|
44
|
-
const path_1 = require("path");
|
|
45
|
-
const fs_1 = require("fs");
|
|
46
|
-
const readline = __importStar(require("readline"));
|
|
47
|
-
const CONFIG_PATH = (0, path_1.join)((0, os_1.homedir)(), ".suron-config");
|
|
48
|
-
function readConfig() {
|
|
49
|
-
if (!(0, fs_1.existsSync)(CONFIG_PATH))
|
|
50
|
-
return {};
|
|
51
|
-
try {
|
|
52
|
-
const lines = (0, fs_1.readFileSync)(CONFIG_PATH, "utf-8").split("\n");
|
|
53
|
-
const config = {};
|
|
54
|
-
for (const line of lines) {
|
|
55
|
-
const [key, ...rest] = line.split("=");
|
|
56
|
-
const value = rest.join("=").trim();
|
|
57
|
-
if (!value)
|
|
58
|
-
continue;
|
|
59
|
-
if (key === "SURON_API_URL")
|
|
60
|
-
config.apiUrl = value;
|
|
61
|
-
if (key === "VAULT_API_KEY")
|
|
62
|
-
config.apiKey = value;
|
|
63
|
-
}
|
|
64
|
-
return config;
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
return {};
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
function saveConfig(values) {
|
|
71
|
-
const current = readConfig();
|
|
72
|
-
const merged = { ...current, ...values };
|
|
73
|
-
const lines = [];
|
|
74
|
-
if (merged.apiUrl)
|
|
75
|
-
lines.push(`SURON_API_URL=${merged.apiUrl}`);
|
|
76
|
-
if (merged.apiKey)
|
|
77
|
-
lines.push(`VAULT_API_KEY=${merged.apiKey}`);
|
|
78
|
-
(0, fs_1.writeFileSync)(CONFIG_PATH, lines.join("\n") + "\n", { mode: 0o600 });
|
|
79
|
-
}
|
|
80
|
-
function getApiUrl() {
|
|
81
|
-
return process.env.SURON_API_URL?.replace(/\/$/, "") ?? readConfig().apiUrl ?? null;
|
|
82
|
-
}
|
|
83
|
-
function getApiKey() {
|
|
84
|
-
return readConfig().apiKey ?? null;
|
|
85
|
-
}
|
|
86
|
-
function saveApiKey(key) {
|
|
87
|
-
saveConfig({ apiKey: key });
|
|
88
|
-
}
|
|
89
|
-
function requireApiUrl() {
|
|
90
|
-
const url = getApiUrl();
|
|
91
|
-
if (!url) {
|
|
92
|
-
console.error("error: not configured. Run: suron login");
|
|
93
|
-
process.exit(1);
|
|
94
|
-
}
|
|
95
|
-
return url;
|
|
96
|
-
}
|
|
97
|
-
function requireApiKey() {
|
|
98
|
-
const key = getApiKey();
|
|
99
|
-
if (!key) {
|
|
100
|
-
console.error("error: not logged in. Run: suron login");
|
|
101
|
-
process.exit(1);
|
|
102
|
-
}
|
|
103
|
-
return key;
|
|
104
|
-
}
|
|
105
|
-
function prompt(question) {
|
|
106
|
-
const rl = readline.createInterface({
|
|
107
|
-
input: process.stdin,
|
|
108
|
-
output: process.stdout,
|
|
109
|
-
});
|
|
110
|
-
return new Promise((resolve) => {
|
|
111
|
-
rl.question(question, (answer) => {
|
|
112
|
-
rl.close();
|
|
113
|
-
resolve(answer.trim());
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
//# sourceMappingURL=config.js.map
|
package/dist/utils/config.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/dotenvx.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Runs: dotenvx encrypt
|
|
3
|
-
* Requires @dotenvx/dotenvx to be installed globally or in path.
|
|
4
|
-
* After encryption: .env is encrypted, .env.keys holds the private key.
|
|
5
|
-
*/
|
|
6
|
-
export declare function encryptDotenv(cwd: string): void;
|
|
7
|
-
/**
|
|
8
|
-
* Reads DOTENV_PRIVATE_KEY from .env.keys file.
|
|
9
|
-
*/
|
|
10
|
-
export declare function readPrivateKey(cwd: string): string;
|
|
11
|
-
/**
|
|
12
|
-
* Deletes .env.keys — called after private key is stored in Convex.
|
|
13
|
-
*/
|
|
14
|
-
export declare function deleteKeysFile(cwd: string): void;
|
package/dist/utils/dotenvx.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.encryptDotenv = encryptDotenv;
|
|
4
|
-
exports.readPrivateKey = readPrivateKey;
|
|
5
|
-
exports.deleteKeysFile = deleteKeysFile;
|
|
6
|
-
const child_process_1 = require("child_process");
|
|
7
|
-
const fs_1 = require("fs");
|
|
8
|
-
const path_1 = require("path");
|
|
9
|
-
/**
|
|
10
|
-
* Runs: dotenvx encrypt
|
|
11
|
-
* Requires @dotenvx/dotenvx to be installed globally or in path.
|
|
12
|
-
* After encryption: .env is encrypted, .env.keys holds the private key.
|
|
13
|
-
*/
|
|
14
|
-
function encryptDotenv(cwd) {
|
|
15
|
-
const dotenvPath = (0, path_1.join)(cwd, ".env");
|
|
16
|
-
if (!(0, fs_1.existsSync)(dotenvPath)) {
|
|
17
|
-
throw new Error(`.env not found in ${cwd}`);
|
|
18
|
-
}
|
|
19
|
-
(0, child_process_1.execSync)("npx @dotenvx/dotenvx encrypt", { cwd, stdio: "inherit" });
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Reads DOTENV_PRIVATE_KEY from .env.keys file.
|
|
23
|
-
*/
|
|
24
|
-
function readPrivateKey(cwd) {
|
|
25
|
-
const keysPath = (0, path_1.join)(cwd, ".env.keys");
|
|
26
|
-
if (!(0, fs_1.existsSync)(keysPath)) {
|
|
27
|
-
throw new Error(".env.keys not found after encryption");
|
|
28
|
-
}
|
|
29
|
-
const { readFileSync } = require("fs");
|
|
30
|
-
const content = readFileSync(keysPath, "utf-8");
|
|
31
|
-
const match = content.match(/DOTENV_PRIVATE_KEY(?:_\w+)?="?([^"\n]+)"?/);
|
|
32
|
-
if (!match?.[1]) {
|
|
33
|
-
throw new Error("Could not parse DOTENV_PRIVATE_KEY from .env.keys");
|
|
34
|
-
}
|
|
35
|
-
return match[1].trim();
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Deletes .env.keys — called after private key is stored in Convex.
|
|
39
|
-
*/
|
|
40
|
-
function deleteKeysFile(cwd) {
|
|
41
|
-
const keysPath = (0, path_1.join)(cwd, ".env.keys");
|
|
42
|
-
if ((0, fs_1.existsSync)(keysPath)) {
|
|
43
|
-
const { unlinkSync } = require("fs");
|
|
44
|
-
unlinkSync(keysPath);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
//# sourceMappingURL=dotenvx.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dotenvx.js","sourceRoot":"","sources":["../../src/utils/dotenvx.ts"],"names":[],"mappings":";;AASA,sCAMC;AAKD,wCAaC;AAKD,wCAMC;AA5CD,iDAAyC;AACzC,2BAAgC;AAChC,+BAA4B;AAE5B;;;;GAIG;AACH,SAAgB,aAAa,CAAC,GAAW;IACvC,MAAM,UAAU,GAAG,IAAA,WAAI,EAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,IAAA,eAAU,EAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,IAAA,wBAAQ,EAAC,8BAA8B,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,GAAW;IACxC,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACxC,IAAI,CAAC,IAAA,eAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAwB,CAAC;IAC9D,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;IACzE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,GAAW;IACxC,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACxC,IAAI,IAAA,eAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAwB,CAAC;QAC5D,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
|