@elding/cli 0.2.0 → 0.8.0
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/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.js +58 -0
- package/dist/commands/init.js +29 -5
- package/dist/commands/keys.d.ts +1 -0
- package/dist/commands/keys.js +31 -0
- package/dist/commands/login.js +40 -25
- package/dist/commands/open.d.ts +1 -0
- package/dist/commands/open.js +13 -0
- package/dist/commands/proxy.d.ts +6 -1
- package/dist/commands/proxy.js +23 -7
- package/dist/commands/run.d.ts +4 -1
- package/dist/commands/run.js +17 -6
- package/dist/commands/sets.d.ts +1 -0
- package/dist/commands/sets.js +26 -0
- package/dist/commands/status.js +3 -2
- package/dist/commands/use.d.ts +1 -0
- package/dist/commands/use.js +37 -0
- package/dist/commands/whoami.d.ts +1 -0
- package/dist/commands/whoami.js +12 -0
- package/dist/index.js +75 -9
- package/dist/lib/api.d.ts +11 -1
- package/dist/lib/api.js +65 -20
- package/dist/lib/apiUrl.d.ts +1 -0
- package/dist/lib/apiUrl.js +44 -0
- package/dist/lib/config.d.ts +11 -0
- package/dist/lib/config.js +100 -7
- package/dist/lib/env.d.ts +5 -0
- package/dist/lib/env.js +49 -0
- package/dist/lib/keychain.d.ts +3 -0
- package/dist/lib/keychain.js +39 -0
- package/dist/lib/logBatcher.d.ts +5 -0
- package/dist/lib/logBatcher.js +42 -0
- package/dist/lib/proxyServer.d.ts +10 -1
- package/dist/lib/proxyServer.js +219 -48
- package/dist/lib/session.d.ts +1 -0
- package/dist/lib/session.js +17 -0
- package/dist/lib/terminal.d.ts +2 -0
- package/dist/lib/terminal.js +15 -0
- package/dist/lib/trust.d.ts +2 -0
- package/dist/lib/trust.js +33 -0
- package/package.json +11 -10
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function doctor(): Promise<void>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.doctor = doctor;
|
|
4
|
+
const config_js_1 = require("../lib/config.js");
|
|
5
|
+
const api_js_1 = require("../lib/api.js");
|
|
6
|
+
const terminal_js_1 = require("../lib/terminal.js");
|
|
7
|
+
async function doctor() {
|
|
8
|
+
const { default: chalk } = await import("chalk");
|
|
9
|
+
const ok = (m) => console.log(`${chalk.green("✓")} ${m}`);
|
|
10
|
+
const warn = (m) => console.log(`${chalk.yellow("!")} ${m}`);
|
|
11
|
+
const fail = (m) => console.log(`${chalk.red("✗")} ${m}`);
|
|
12
|
+
console.log(chalk.dim(`API : ${api_js_1.BASE_URL}\n`));
|
|
13
|
+
// 1. Token local
|
|
14
|
+
const config = (0, config_js_1.readConfig)();
|
|
15
|
+
if (!config) {
|
|
16
|
+
fail("Non connecté — lancez `elding login`");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
ok("Token local présent (trousseau OS)");
|
|
20
|
+
// 2. Token valide + utilisateur
|
|
21
|
+
let accessToken;
|
|
22
|
+
try {
|
|
23
|
+
accessToken = await (0, api_js_1.exchangeToken)(config.refreshToken);
|
|
24
|
+
const me = await (0, api_js_1.getMe)(accessToken);
|
|
25
|
+
ok(`Authentifié : ${(0, terminal_js_1.safeText)(me.email)}`);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
fail("Token expiré ou révoqué — relancez `elding login`");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
// 3. Set du projet
|
|
32
|
+
const project = (0, config_js_1.readProject)();
|
|
33
|
+
if (!project) {
|
|
34
|
+
warn("Aucun set configuré — lancez `elding init` ou `elding use <set>`");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
ok(`Set actif : ${(0, terminal_js_1.safeText)(project.setName)}`);
|
|
38
|
+
// 4. Clés + verrouillage host
|
|
39
|
+
try {
|
|
40
|
+
const keys = await (0, api_js_1.listKeys)(accessToken, project.setId);
|
|
41
|
+
if (keys.length === 0)
|
|
42
|
+
warn("Le set ne contient aucune clé");
|
|
43
|
+
else {
|
|
44
|
+
const locked = keys.filter((k) => k.allowedHost).length;
|
|
45
|
+
ok(`${keys.length} clé(s) — ${locked} verrouillée(s) sur un domaine`);
|
|
46
|
+
if (locked < keys.length)
|
|
47
|
+
warn(`${keys.length - locked} clé(s) sans domaine : exfiltrables via le proxy`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
fail("Impossible de lire les clés du set");
|
|
52
|
+
}
|
|
53
|
+
// 5. Proxy
|
|
54
|
+
if (process.env.ELDING_PROXY_URL)
|
|
55
|
+
ok(`Proxy actif : ${process.env.ELDING_PROXY_URL}`);
|
|
56
|
+
else
|
|
57
|
+
console.log(chalk.dim("○ Proxy inactif (normal hors `elding proxy`)"));
|
|
58
|
+
}
|
package/dist/commands/init.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.init = init;
|
|
4
4
|
const config_js_1 = require("../lib/config.js");
|
|
5
5
|
const api_js_1 = require("../lib/api.js");
|
|
6
|
+
const terminal_js_1 = require("../lib/terminal.js");
|
|
6
7
|
async function init() {
|
|
7
8
|
const { default: chalk } = await import("chalk");
|
|
8
9
|
const { default: ora } = await import("ora");
|
|
@@ -31,19 +32,42 @@ async function init() {
|
|
|
31
32
|
process.exit(1);
|
|
32
33
|
}
|
|
33
34
|
if (sets.length === 0) {
|
|
34
|
-
console.log(chalk.yellow("Aucun set trouvé. Créez-en un sur
|
|
35
|
+
console.log(chalk.yellow("Aucun set trouvé. Créez-en un sur le vault."));
|
|
35
36
|
process.exit(0);
|
|
36
37
|
}
|
|
38
|
+
// Étape 1 : choisir l'organisation (sauf s'il n'y en a qu'une)
|
|
39
|
+
const orgs = [...new Map(sets.map((s) => [s.workspaceId, s.workspaceName])).entries()];
|
|
40
|
+
let workspaceId = orgs[0][0];
|
|
41
|
+
if (orgs.length > 1) {
|
|
42
|
+
const ans = await inquirer.prompt([
|
|
43
|
+
{
|
|
44
|
+
type: "list",
|
|
45
|
+
name: "workspaceId",
|
|
46
|
+
message: "Quelle organisation ?",
|
|
47
|
+
choices: orgs.map(([id, name]) => ({ name: (0, terminal_js_1.safeText)(name), value: id })),
|
|
48
|
+
},
|
|
49
|
+
]);
|
|
50
|
+
workspaceId = ans.workspaceId;
|
|
51
|
+
}
|
|
52
|
+
// Étape 2 : choisir le set parmi ceux de l'org
|
|
53
|
+
const orgSets = sets.filter((s) => s.workspaceId === workspaceId);
|
|
37
54
|
const { setId } = await inquirer.prompt([
|
|
38
55
|
{
|
|
39
56
|
type: "list",
|
|
40
57
|
name: "setId",
|
|
41
58
|
message: "Quel set utiliser pour ce projet ?",
|
|
42
|
-
choices:
|
|
59
|
+
choices: orgSets.map((s) => ({ name: (0, terminal_js_1.safeText)(s.name), value: s.id })),
|
|
43
60
|
},
|
|
44
61
|
]);
|
|
45
|
-
const selected =
|
|
46
|
-
|
|
47
|
-
|
|
62
|
+
const selected = orgSets.find((s) => s.id === setId);
|
|
63
|
+
const project = {
|
|
64
|
+
setId: selected.id,
|
|
65
|
+
setName: selected.name,
|
|
66
|
+
workspaceId: selected.workspaceId,
|
|
67
|
+
workspaceName: selected.workspaceName,
|
|
68
|
+
};
|
|
69
|
+
(0, config_js_1.writeProject)(project);
|
|
70
|
+
(0, config_js_1.trustProject)(project);
|
|
71
|
+
console.log(chalk.green(`✓ Set "${(0, terminal_js_1.safeText)(selected.name)}" (${(0, terminal_js_1.safeText)(selected.workspaceName)}) configuré dans .elding.json`));
|
|
48
72
|
console.log(chalk.dim("Ajoutez .elding.json à votre .gitignore si besoin."));
|
|
49
73
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function keys(): Promise<void>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.keys = keys;
|
|
4
|
+
const api_js_1 = require("../lib/api.js");
|
|
5
|
+
const config_js_1 = require("../lib/config.js");
|
|
6
|
+
const session_js_1 = require("../lib/session.js");
|
|
7
|
+
const terminal_js_1 = require("../lib/terminal.js");
|
|
8
|
+
async function keys() {
|
|
9
|
+
const { default: chalk } = await import("chalk");
|
|
10
|
+
const { default: ora } = await import("ora");
|
|
11
|
+
const project = (0, config_js_1.readProject)();
|
|
12
|
+
if (!project) {
|
|
13
|
+
console.error(chalk.red("Projet non initialisé. Lancez `elding init` ou `elding use <set>`."));
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
const spinner = ora("Récupération des clés...").start();
|
|
17
|
+
const accessToken = await (0, session_js_1.requireAccessToken)();
|
|
18
|
+
const list = await (0, api_js_1.listKeys)(accessToken, project.setId);
|
|
19
|
+
spinner.stop();
|
|
20
|
+
console.log(chalk.dim(`Set : ${(0, terminal_js_1.safeText)(project.setName)}`));
|
|
21
|
+
if (list.length === 0) {
|
|
22
|
+
console.log(chalk.yellow("Aucune clé dans ce set."));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
for (const k of list) {
|
|
26
|
+
const host = k.allowedHost
|
|
27
|
+
? chalk.dim(` → ${(0, terminal_js_1.safeText)(k.allowedHost)}`)
|
|
28
|
+
: chalk.yellow(" → aucun domaine (non verrouillé)");
|
|
29
|
+
console.log(` ${(0, terminal_js_1.safeText)(k.name)}${host}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
package/dist/commands/login.js
CHANGED
|
@@ -7,52 +7,67 @@ exports.login = login;
|
|
|
7
7
|
const http_1 = __importDefault(require("http"));
|
|
8
8
|
const crypto_1 = __importDefault(require("crypto"));
|
|
9
9
|
const config_js_1 = require("../lib/config.js");
|
|
10
|
-
const
|
|
10
|
+
const api_js_1 = require("../lib/api.js");
|
|
11
|
+
const terminal_js_1 = require("../lib/terminal.js");
|
|
11
12
|
const TIMEOUT_MS = 5 * 60 * 1000;
|
|
12
|
-
function randomPort() {
|
|
13
|
-
return Math.floor(Math.random() * (65535 - 49152 + 1)) + 49152;
|
|
14
|
-
}
|
|
15
13
|
async function login() {
|
|
16
14
|
const { default: chalk } = await import("chalk");
|
|
17
15
|
const { default: open } = await import("open");
|
|
18
16
|
const { default: ora } = await import("ora");
|
|
19
17
|
const state = crypto_1.default.randomBytes(16).toString("hex");
|
|
20
|
-
const port = randomPort();
|
|
21
|
-
const callbackUrl = `http://localhost:${port}`;
|
|
22
|
-
const authUrl = `${BASE_URL}/cli` +
|
|
23
|
-
`?state=${encodeURIComponent(state)}` +
|
|
24
|
-
`&callback=${encodeURIComponent(callbackUrl)}`;
|
|
25
18
|
const spinner = ora("En attente d'autorisation dans le navigateur...").start();
|
|
26
19
|
const token = await new Promise((resolve, reject) => {
|
|
27
20
|
const timeout = setTimeout(() => {
|
|
28
21
|
server.close();
|
|
29
22
|
reject(new Error("Timeout — aucune réponse après 5 minutes"));
|
|
30
23
|
}, TIMEOUT_MS);
|
|
31
|
-
const server = http_1.default.createServer((req, res) => {
|
|
32
|
-
const
|
|
33
|
-
const
|
|
24
|
+
const server = http_1.default.createServer(async (req, res) => {
|
|
25
|
+
const addr = server.address();
|
|
26
|
+
const port = typeof addr === "object" && addr ? addr.port : 0;
|
|
27
|
+
const callbackUrl = `http://127.0.0.1:${port}`;
|
|
28
|
+
const url = new URL(req.url ?? "/", callbackUrl);
|
|
29
|
+
const receivedCode = url.searchParams.get("code");
|
|
34
30
|
const receivedState = url.searchParams.get("state");
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (receivedState !== state || !tokenValid) {
|
|
31
|
+
const codeValid = typeof receivedCode === "string" &&
|
|
32
|
+
/^[A-Za-z0-9._~-]{16,512}$/.test(receivedCode);
|
|
33
|
+
if (receivedState !== state || !codeValid) {
|
|
39
34
|
res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
|
|
40
35
|
res.end("<p>Paramètres invalides. Fermez cet onglet.</p>");
|
|
41
36
|
return;
|
|
42
37
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
try {
|
|
39
|
+
const refreshToken = await (0, api_js_1.exchangeLoginCode)(receivedCode, state, callbackUrl);
|
|
40
|
+
res.writeHead(200, {
|
|
41
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
42
|
+
"Referrer-Policy": "no-referrer",
|
|
43
|
+
"Cache-Control": "no-store",
|
|
44
|
+
});
|
|
45
|
+
res.end(`<!DOCTYPE html><html><head><meta charset="utf-8"><script>history.replaceState(null,"","/")</script></head><body style="font-family:sans-serif;padding:2rem">
|
|
46
|
+
<p><strong>Authentification réussie.</strong> Vous pouvez fermer cet onglet.</p>
|
|
47
|
+
</body></html>`);
|
|
48
|
+
clearTimeout(timeout);
|
|
49
|
+
server.close();
|
|
50
|
+
resolve(refreshToken);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
res.writeHead(502, { "Content-Type": "text/html; charset=utf-8" });
|
|
54
|
+
res.end("<p>Impossible de finaliser l'authentification. Fermez cet onglet et relancez le login.</p>");
|
|
55
|
+
clearTimeout(timeout);
|
|
56
|
+
server.close();
|
|
57
|
+
reject(new Error((0, terminal_js_1.safeError)(err)));
|
|
58
|
+
}
|
|
50
59
|
});
|
|
51
60
|
server.on("error", (err) => {
|
|
52
61
|
clearTimeout(timeout);
|
|
53
62
|
reject(err);
|
|
54
63
|
});
|
|
55
|
-
server.listen(
|
|
64
|
+
server.listen(0, "127.0.0.1", () => {
|
|
65
|
+
const addr = server.address();
|
|
66
|
+
const port = typeof addr === "object" && addr ? addr.port : 0;
|
|
67
|
+
const callbackUrl = `http://127.0.0.1:${port}`;
|
|
68
|
+
const authUrl = `${api_js_1.BASE_URL}/cli` +
|
|
69
|
+
`?state=${encodeURIComponent(state)}` +
|
|
70
|
+
`&callback=${encodeURIComponent(callbackUrl)}`;
|
|
56
71
|
open(authUrl).catch((err) => {
|
|
57
72
|
spinner.warn(`Impossible d'ouvrir le navigateur automatiquement.`);
|
|
58
73
|
console.log(chalk.cyan(`Ouvrez manuellement : ${authUrl}`));
|
|
@@ -61,5 +76,5 @@ async function login() {
|
|
|
61
76
|
});
|
|
62
77
|
(0, config_js_1.writeConfig)({ refreshToken: token });
|
|
63
78
|
spinner.succeed(chalk.green("Connecté avec succès."));
|
|
64
|
-
console.log(chalk.dim("Token sauvegardé dans
|
|
79
|
+
console.log(chalk.dim("Token sauvegardé dans le trousseau de votre OS."));
|
|
65
80
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function open(): Promise<void>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.open = open;
|
|
4
|
+
const api_js_1 = require("../lib/api.js");
|
|
5
|
+
async function open() {
|
|
6
|
+
const { default: chalk } = await import("chalk");
|
|
7
|
+
const { default: openUrl } = await import("open");
|
|
8
|
+
const url = `${api_js_1.BASE_URL}/vault`;
|
|
9
|
+
await openUrl(url).catch(() => {
|
|
10
|
+
console.log(chalk.cyan(`Ouvrez manuellement : ${url}`));
|
|
11
|
+
});
|
|
12
|
+
console.log(chalk.dim(`Vault ouvert : ${url}`));
|
|
13
|
+
}
|
package/dist/commands/proxy.d.ts
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type ProxyOptions = {
|
|
2
|
+
verbose?: boolean;
|
|
3
|
+
reportLogs?: boolean;
|
|
4
|
+
shell?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare function proxy(cmd: string, args: string[], options?: ProxyOptions): Promise<void>;
|
package/dist/commands/proxy.js
CHANGED
|
@@ -5,7 +5,10 @@ const child_process_1 = require("child_process");
|
|
|
5
5
|
const config_js_1 = require("../lib/config.js");
|
|
6
6
|
const api_js_1 = require("../lib/api.js");
|
|
7
7
|
const proxyServer_js_1 = require("../lib/proxyServer.js");
|
|
8
|
-
|
|
8
|
+
const logBatcher_js_1 = require("../lib/logBatcher.js");
|
|
9
|
+
const trust_js_1 = require("../lib/trust.js");
|
|
10
|
+
const terminal_js_1 = require("../lib/terminal.js");
|
|
11
|
+
async function proxy(cmd, args, options = {}) {
|
|
9
12
|
const { default: chalk } = await import("chalk");
|
|
10
13
|
const { default: ora } = await import("ora");
|
|
11
14
|
const config = (0, config_js_1.readConfig)();
|
|
@@ -18,6 +21,10 @@ async function proxy(cmd, args) {
|
|
|
18
21
|
console.error(chalk.red("Projet non initialisé. Lancez `elding init` d'abord."));
|
|
19
22
|
process.exit(1);
|
|
20
23
|
}
|
|
24
|
+
await (0, trust_js_1.ensureProjectTrusted)(project);
|
|
25
|
+
if (!options.shell && /\s/.test(cmd)) {
|
|
26
|
+
throw new Error("Commande invalide sans --shell. Passez le binaire et ses arguments separement, ou ajoutez --shell explicitement.");
|
|
27
|
+
}
|
|
21
28
|
const spinner = ora("Démarrage du proxy...").start();
|
|
22
29
|
let secrets;
|
|
23
30
|
let hosts;
|
|
@@ -26,12 +33,17 @@ async function proxy(cmd, args) {
|
|
|
26
33
|
({ secrets, hosts } = await (0, api_js_1.fetchSecrets)(accessToken, project.setId));
|
|
27
34
|
}
|
|
28
35
|
catch (err) {
|
|
29
|
-
spinner.fail(chalk.red(
|
|
36
|
+
spinner.fail(chalk.red((0, terminal_js_1.safeError)(err)));
|
|
30
37
|
process.exit(1);
|
|
31
38
|
}
|
|
32
|
-
const
|
|
33
|
-
|
|
39
|
+
const batcher = options.reportLogs
|
|
40
|
+
? (0, logBatcher_js_1.createLogBatcher)(config.refreshToken, project.setId, project.setName)
|
|
41
|
+
: null;
|
|
42
|
+
const server = await (0, proxyServer_js_1.startProxy)(secrets, hosts, !!options.verbose, batcher ? (e) => batcher.add(e) : undefined);
|
|
43
|
+
spinner.succeed(chalk.green(`Proxy actif sur ${server.url} — ${Object.keys(secrets).length} secret(s) pour ${(0, terminal_js_1.safeText)(project.setName)}`));
|
|
34
44
|
console.log(chalk.dim("Les clés restent dans le proxy, jamais dans la mémoire de l'app."));
|
|
45
|
+
if (!options.reportLogs)
|
|
46
|
+
console.log(chalk.dim("Logs cloud proxy désactivés. Ajoutez --report-logs pour les envoyer."));
|
|
35
47
|
const child = (0, child_process_1.spawn)(cmd, args, {
|
|
36
48
|
env: {
|
|
37
49
|
...process.env,
|
|
@@ -39,13 +51,17 @@ async function proxy(cmd, args) {
|
|
|
39
51
|
ELDING_PROXY_TOKEN: server.token,
|
|
40
52
|
},
|
|
41
53
|
stdio: "inherit",
|
|
42
|
-
shell:
|
|
54
|
+
shell: !!options.shell,
|
|
43
55
|
});
|
|
44
|
-
const shutdown = () =>
|
|
56
|
+
const shutdown = async () => {
|
|
57
|
+
server.close();
|
|
58
|
+
await batcher?.stop();
|
|
59
|
+
};
|
|
45
60
|
process.on("SIGINT", shutdown);
|
|
46
61
|
process.on("SIGTERM", shutdown);
|
|
47
|
-
child.on("exit", (code) => {
|
|
62
|
+
child.on("exit", async (code) => {
|
|
48
63
|
server.close();
|
|
64
|
+
await batcher?.stop(); // flush les derniers logs
|
|
49
65
|
process.exit(code ?? 0);
|
|
50
66
|
});
|
|
51
67
|
}
|
package/dist/commands/run.d.ts
CHANGED
package/dist/commands/run.js
CHANGED
|
@@ -4,7 +4,10 @@ exports.run = run;
|
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const config_js_1 = require("../lib/config.js");
|
|
6
6
|
const api_js_1 = require("../lib/api.js");
|
|
7
|
-
|
|
7
|
+
const env_js_1 = require("../lib/env.js");
|
|
8
|
+
const trust_js_1 = require("../lib/trust.js");
|
|
9
|
+
const terminal_js_1 = require("../lib/terminal.js");
|
|
10
|
+
async function run(cmd, args, options = {}) {
|
|
8
11
|
const { default: chalk } = await import("chalk");
|
|
9
12
|
const { default: ora } = await import("ora");
|
|
10
13
|
const config = (0, config_js_1.readConfig)();
|
|
@@ -17,22 +20,30 @@ async function run(cmd, args) {
|
|
|
17
20
|
console.error(chalk.red("Projet non initialisé. Lancez `elding init` d'abord."));
|
|
18
21
|
process.exit(1);
|
|
19
22
|
}
|
|
23
|
+
await (0, trust_js_1.ensureProjectTrusted)(project);
|
|
24
|
+
if (!options.shell && /\s/.test(cmd)) {
|
|
25
|
+
throw new Error("Commande invalide sans --shell. Passez le binaire et ses arguments separement, ou ajoutez --shell explicitement.");
|
|
26
|
+
}
|
|
20
27
|
const spinner = ora("Récupération des secrets...").start();
|
|
21
28
|
let secrets;
|
|
22
29
|
try {
|
|
23
30
|
const accessToken = await (0, api_js_1.exchangeToken)(config.refreshToken);
|
|
24
|
-
({ secrets } = await (0, api_js_1.fetchSecrets)(accessToken, project.setId));
|
|
25
|
-
spinner.succeed(chalk.green(`${Object.keys(secrets).length} secret(s) chargé(s).`));
|
|
31
|
+
({ secrets } = await (0, api_js_1.fetchSecrets)(accessToken, project.setId, "run"));
|
|
32
|
+
spinner.succeed(chalk.green(`${Object.keys(secrets).length} secret(s) chargé(s) pour ${(0, terminal_js_1.safeText)(project.setName)}.`));
|
|
26
33
|
}
|
|
27
34
|
catch (err) {
|
|
28
|
-
spinner.fail(chalk.red(
|
|
35
|
+
spinner.fail(chalk.red((0, terminal_js_1.safeError)(err)));
|
|
29
36
|
process.exit(1);
|
|
30
37
|
}
|
|
31
|
-
const env =
|
|
38
|
+
const { env: safeSecrets, rejected } = (0, env_js_1.filterSecretsForEnv)(secrets);
|
|
39
|
+
if (rejected.length > 0) {
|
|
40
|
+
throw new Error(`Secrets refuses car leurs noms sont dangereux pour l'environnement: ${rejected.map((name) => (0, terminal_js_1.safeText)(name, 80)).join(", ")}`);
|
|
41
|
+
}
|
|
42
|
+
const env = { ...process.env, ...safeSecrets };
|
|
32
43
|
const result = (0, child_process_1.spawnSync)(cmd, args, {
|
|
33
44
|
env,
|
|
34
45
|
stdio: "inherit",
|
|
35
|
-
shell:
|
|
46
|
+
shell: !!options.shell,
|
|
36
47
|
});
|
|
37
48
|
if (result.error) {
|
|
38
49
|
console.error(chalk.red(`Impossible de lancer la commande : ${result.error.message}`));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function sets(): Promise<void>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sets = sets;
|
|
4
|
+
const api_js_1 = require("../lib/api.js");
|
|
5
|
+
const config_js_1 = require("../lib/config.js");
|
|
6
|
+
const session_js_1 = require("../lib/session.js");
|
|
7
|
+
const terminal_js_1 = require("../lib/terminal.js");
|
|
8
|
+
async function sets() {
|
|
9
|
+
const { default: chalk } = await import("chalk");
|
|
10
|
+
const { default: ora } = await import("ora");
|
|
11
|
+
const spinner = ora("Récupération des sets...").start();
|
|
12
|
+
const accessToken = await (0, session_js_1.requireAccessToken)();
|
|
13
|
+
const list = await (0, api_js_1.listSets)(accessToken);
|
|
14
|
+
spinner.stop();
|
|
15
|
+
if (list.length === 0) {
|
|
16
|
+
console.log(chalk.yellow("Aucun set. Créez-en un sur le vault."));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const activeId = (0, config_js_1.readProject)()?.setId;
|
|
20
|
+
for (const s of list) {
|
|
21
|
+
const marker = s.id === activeId ? chalk.green("●") : chalk.dim("○");
|
|
22
|
+
const cleanName = (0, terminal_js_1.safeText)(s.name);
|
|
23
|
+
const name = s.id === activeId ? chalk.green(cleanName) : cleanName;
|
|
24
|
+
console.log(`${marker} ${name} ${chalk.dim(`(${(0, terminal_js_1.safeText)(s.workspaceName)})`)}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
package/dist/commands/status.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.status = status;
|
|
4
4
|
const config_js_1 = require("../lib/config.js");
|
|
5
5
|
const api_js_1 = require("../lib/api.js");
|
|
6
|
+
const terminal_js_1 = require("../lib/terminal.js");
|
|
6
7
|
async function status() {
|
|
7
8
|
const { default: chalk } = await import("chalk");
|
|
8
9
|
const config = (0, config_js_1.readConfig)();
|
|
@@ -23,7 +24,7 @@ async function status() {
|
|
|
23
24
|
const project = (0, config_js_1.readProject)();
|
|
24
25
|
const proxyActive = !!process.env.ELDING_PROXY_URL;
|
|
25
26
|
console.log(chalk.green("● Connecté"));
|
|
26
|
-
console.log(` ${chalk.dim("Utilisateur")} ${user.email}${user.name ? chalk.dim(` (${user.name})`) : ""}`);
|
|
27
|
-
console.log(` ${chalk.dim("Set actif")} ${project ? `${project.setName} ${chalk.dim(`(${project.setId})`)}` : chalk.yellow("aucun — `elding init`")}`);
|
|
27
|
+
console.log(` ${chalk.dim("Utilisateur")} ${(0, terminal_js_1.safeText)(user.email)}${user.name ? chalk.dim(` (${(0, terminal_js_1.safeText)(user.name)})`) : ""}`);
|
|
28
|
+
console.log(` ${chalk.dim("Set actif")} ${project ? `${(0, terminal_js_1.safeText)(project.setName)} ${chalk.dim(`(${(0, terminal_js_1.safeText)(project.setId)})`)}` : chalk.yellow("aucun — `elding init`")}`);
|
|
28
29
|
console.log(` ${chalk.dim("Proxy")} ${proxyActive ? chalk.green("actif") : chalk.dim("inactif")}`);
|
|
29
30
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function use(nameArg: string): Promise<void>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.use = use;
|
|
4
|
+
const api_js_1 = require("../lib/api.js");
|
|
5
|
+
const config_js_1 = require("../lib/config.js");
|
|
6
|
+
const session_js_1 = require("../lib/session.js");
|
|
7
|
+
const terminal_js_1 = require("../lib/terminal.js");
|
|
8
|
+
async function use(nameArg) {
|
|
9
|
+
const { default: chalk } = await import("chalk");
|
|
10
|
+
const { default: ora } = await import("ora");
|
|
11
|
+
const spinner = ora("Récupération des sets...").start();
|
|
12
|
+
const accessToken = await (0, session_js_1.requireAccessToken)();
|
|
13
|
+
const list = await (0, api_js_1.listSets)(accessToken);
|
|
14
|
+
spinner.stop();
|
|
15
|
+
const query = nameArg.trim().toLowerCase();
|
|
16
|
+
const matches = list.filter((s) => s.name.toLowerCase() === query);
|
|
17
|
+
const candidates = matches.length ? matches : list.filter((s) => s.name.toLowerCase().includes(query));
|
|
18
|
+
if (candidates.length === 0) {
|
|
19
|
+
console.error(chalk.red(`Aucun set nommé "${(0, terminal_js_1.safeText)(nameArg)}".`) + chalk.dim(" Voir `elding sets`."));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
if (candidates.length > 1) {
|
|
23
|
+
console.error(chalk.red(`Plusieurs sets correspondent à "${(0, terminal_js_1.safeText)(nameArg)}" :`));
|
|
24
|
+
candidates.forEach((s) => console.error(chalk.dim(` - ${(0, terminal_js_1.safeText)(s.name)}`)));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
const set = candidates[0];
|
|
28
|
+
const project = {
|
|
29
|
+
setId: set.id,
|
|
30
|
+
setName: set.name,
|
|
31
|
+
workspaceId: set.workspaceId,
|
|
32
|
+
workspaceName: set.workspaceName,
|
|
33
|
+
};
|
|
34
|
+
(0, config_js_1.writeProject)(project);
|
|
35
|
+
(0, config_js_1.trustProject)(project);
|
|
36
|
+
console.log(chalk.green(`✓ Set actif : "${(0, terminal_js_1.safeText)(set.name)}"`));
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function whoami(): Promise<void>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.whoami = whoami;
|
|
4
|
+
const api_js_1 = require("../lib/api.js");
|
|
5
|
+
const session_js_1 = require("../lib/session.js");
|
|
6
|
+
const terminal_js_1 = require("../lib/terminal.js");
|
|
7
|
+
async function whoami() {
|
|
8
|
+
const { default: chalk } = await import("chalk");
|
|
9
|
+
const accessToken = await (0, session_js_1.requireAccessToken)();
|
|
10
|
+
const me = await (0, api_js_1.getMe)(accessToken);
|
|
11
|
+
console.log(`${(0, terminal_js_1.safeText)(me.email)}${me.name ? chalk.dim(` (${(0, terminal_js_1.safeText)(me.name)})`) : ""}`);
|
|
12
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -8,11 +8,17 @@ const run_js_1 = require("./commands/run.js");
|
|
|
8
8
|
const proxy_js_1 = require("./commands/proxy.js");
|
|
9
9
|
const logout_js_1 = require("./commands/logout.js");
|
|
10
10
|
const status_js_1 = require("./commands/status.js");
|
|
11
|
+
const sets_js_1 = require("./commands/sets.js");
|
|
12
|
+
const use_js_1 = require("./commands/use.js");
|
|
13
|
+
const keys_js_1 = require("./commands/keys.js");
|
|
14
|
+
const doctor_js_1 = require("./commands/doctor.js");
|
|
15
|
+
const open_js_1 = require("./commands/open.js");
|
|
16
|
+
const whoami_js_1 = require("./commands/whoami.js");
|
|
11
17
|
const program = new commander_1.Command();
|
|
12
18
|
program
|
|
13
19
|
.name("elding")
|
|
14
20
|
.description("Elding CLI — secrets depuis le vault, zéro .env")
|
|
15
|
-
.version("0.
|
|
21
|
+
.version("0.3.0");
|
|
16
22
|
program
|
|
17
23
|
.command("login")
|
|
18
24
|
.description("Authentifier le CLI via le navigateur")
|
|
@@ -32,23 +38,29 @@ program
|
|
|
32
38
|
});
|
|
33
39
|
});
|
|
34
40
|
program
|
|
35
|
-
.command("run <cmd>")
|
|
41
|
+
.command("run <cmd> [args...]")
|
|
36
42
|
.description("Lancer une commande avec les secrets injectés en variables d'environnement")
|
|
43
|
+
.option("--shell", "Executer via le shell systeme (a utiliser seulement si necessaire)")
|
|
37
44
|
.allowUnknownOption()
|
|
38
|
-
.action(async (cmd,
|
|
39
|
-
|
|
40
|
-
await (0, run_js_1.run)(cmd, args).catch((err) => {
|
|
45
|
+
.action(async (cmd, args = [], options) => {
|
|
46
|
+
await (0, run_js_1.run)(cmd, args, { shell: !!options.shell }).catch((err) => {
|
|
41
47
|
console.error(err.message);
|
|
42
48
|
process.exit(1);
|
|
43
49
|
});
|
|
44
50
|
});
|
|
45
51
|
program
|
|
46
|
-
.command("proxy <cmd>")
|
|
52
|
+
.command("proxy <cmd> [args...]")
|
|
47
53
|
.description("Lancer une commande derrière un proxy local qui injecte les clés — jamais en mémoire de l'app")
|
|
54
|
+
.option("-v, --verbose", "Logger chaque requête (méthode/host/status/latence)")
|
|
55
|
+
.option("--report-logs", "Envoyer les metadonnees de requetes proxy au vault")
|
|
56
|
+
.option("--shell", "Executer via le shell systeme (a utiliser seulement si necessaire)")
|
|
48
57
|
.allowUnknownOption()
|
|
49
|
-
.action(async (cmd,
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
.action(async (cmd, args = [], options) => {
|
|
59
|
+
await (0, proxy_js_1.proxy)(cmd, args, {
|
|
60
|
+
verbose: !!options.verbose,
|
|
61
|
+
reportLogs: !!options.reportLogs,
|
|
62
|
+
shell: !!options.shell,
|
|
63
|
+
}).catch((err) => {
|
|
52
64
|
console.error(err.message);
|
|
53
65
|
process.exit(1);
|
|
54
66
|
});
|
|
@@ -71,4 +83,58 @@ program
|
|
|
71
83
|
process.exit(1);
|
|
72
84
|
});
|
|
73
85
|
});
|
|
86
|
+
program
|
|
87
|
+
.command("sets")
|
|
88
|
+
.description("Lister les sets accessibles")
|
|
89
|
+
.action(async () => {
|
|
90
|
+
await (0, sets_js_1.sets)().catch((err) => {
|
|
91
|
+
console.error(err.message);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
program
|
|
96
|
+
.command("use <name>")
|
|
97
|
+
.description("Changer le set actif du projet")
|
|
98
|
+
.action(async (name) => {
|
|
99
|
+
await (0, use_js_1.use)(name).catch((err) => {
|
|
100
|
+
console.error(err.message);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
program
|
|
105
|
+
.command("keys")
|
|
106
|
+
.description("Lister les noms de clés du set actif (jamais les valeurs)")
|
|
107
|
+
.action(async () => {
|
|
108
|
+
await (0, keys_js_1.keys)().catch((err) => {
|
|
109
|
+
console.error(err.message);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
program
|
|
114
|
+
.command("doctor")
|
|
115
|
+
.description("Diagnostiquer la configuration (connexion, set, clés, proxy)")
|
|
116
|
+
.action(async () => {
|
|
117
|
+
await (0, doctor_js_1.doctor)().catch((err) => {
|
|
118
|
+
console.error(err.message);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
program
|
|
123
|
+
.command("open")
|
|
124
|
+
.description("Ouvrir le vault dans le navigateur")
|
|
125
|
+
.action(async () => {
|
|
126
|
+
await (0, open_js_1.open)().catch((err) => {
|
|
127
|
+
console.error(err.message);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
program
|
|
132
|
+
.command("whoami")
|
|
133
|
+
.description("Afficher l'utilisateur connecté")
|
|
134
|
+
.action(async () => {
|
|
135
|
+
await (0, whoami_js_1.whoami)().catch((err) => {
|
|
136
|
+
console.error(err.message);
|
|
137
|
+
process.exit(1);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
74
140
|
program.parse();
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
export declare const BASE_URL: string;
|
|
1
2
|
export type ApiKeySetItem = {
|
|
2
3
|
id: string;
|
|
3
4
|
name: string;
|
|
5
|
+
workspaceId: string;
|
|
6
|
+
workspaceName: string;
|
|
4
7
|
};
|
|
8
|
+
export type KeyItem = {
|
|
9
|
+
name: string;
|
|
10
|
+
allowedHost: string | null;
|
|
11
|
+
};
|
|
12
|
+
export declare function listKeys(accessToken: string, setId: string): Promise<KeyItem[]>;
|
|
5
13
|
export declare function exchangeToken(refreshToken: string): Promise<string>;
|
|
14
|
+
export declare function exchangeLoginCode(code: string, state: string, callbackUrl: string): Promise<string>;
|
|
15
|
+
export declare function reportProxyLogs(accessToken: string, setId: string, setName: string, entries: unknown[]): Promise<void>;
|
|
6
16
|
export declare function revokeToken(refreshToken: string): Promise<void>;
|
|
7
17
|
export declare function getMe(accessToken: string): Promise<{
|
|
8
18
|
email: string;
|
|
@@ -13,4 +23,4 @@ export type SecretsResult = {
|
|
|
13
23
|
secrets: Record<string, string>;
|
|
14
24
|
hosts: Record<string, string>;
|
|
15
25
|
};
|
|
16
|
-
export declare function fetchSecrets(accessToken: string, setId: string): Promise<SecretsResult>;
|
|
26
|
+
export declare function fetchSecrets(accessToken: string, setId: string, mode?: "run" | "proxy"): Promise<SecretsResult>;
|