@barekey/cli 0.1.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/LICENSE +28 -0
- package/README.md +36 -0
- package/dist/auth-provider.d.ts +6 -0
- package/dist/auth-provider.js +58 -0
- package/dist/command-utils.d.ts +23 -0
- package/dist/command-utils.js +78 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +186 -0
- package/dist/commands/env.d.ts +2 -0
- package/dist/commands/env.js +295 -0
- package/dist/commands/typegen.d.ts +2 -0
- package/dist/commands/typegen.js +25 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +4 -0
- package/dist/credentials-store.d.ts +7 -0
- package/dist/credentials-store.js +199 -0
- package/dist/http.d.ts +22 -0
- package/dist/http.js +66 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +17 -0
- package/dist/runtime-config.d.ts +10 -0
- package/dist/runtime-config.js +49 -0
- package/dist/typegen.d.ts +20 -0
- package/dist/typegen.js +14 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.js +1 -0
- package/package.json +37 -0
- package/src/auth-provider.ts +86 -0
- package/src/command-utils.ts +118 -0
- package/src/commands/auth.ts +247 -0
- package/src/commands/env.ts +496 -0
- package/src/commands/typegen.ts +38 -0
- package/src/constants.ts +4 -0
- package/src/credentials-store.ts +243 -0
- package/src/http.ts +86 -0
- package/src/index.ts +21 -0
- package/src/runtime-config.ts +66 -0
- package/src/types.ts +14 -0
- package/tsconfig.json +13 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, Barekey Inc.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# @barekey/cli
|
|
2
|
+
|
|
3
|
+
CLI for logging into Barekey, managing environment variables, and pulling resolved values into local workflows.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @barekey/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quickstart
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
barekey auth login
|
|
15
|
+
barekey env list --org acme --project api --stage development
|
|
16
|
+
barekey env get DATABASE_URL --org acme --project api --stage development
|
|
17
|
+
barekey env pull --org acme --project api --stage development --out .env
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Common commands
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
barekey auth whoami
|
|
24
|
+
barekey env new FEATURE_FLAG true --type boolean --org acme --project api --stage development
|
|
25
|
+
barekey env set CHECKOUT_COPY original --ab redesign --chance 0.25 --org acme --project api --stage development
|
|
26
|
+
barekey env delete FEATURE_FLAG --yes --org acme --project api --stage development
|
|
27
|
+
barekey env get-many --names DATABASE_URL,FEATURE_FLAG --org acme --project api --stage development
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Development
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install
|
|
34
|
+
npm run build
|
|
35
|
+
npm run typecheck
|
|
36
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { postJson } from "./http.js";
|
|
2
|
+
import { loadConfig, loadCredentials, saveCredentials } from "./credentials-store.js";
|
|
3
|
+
export function createCliAuthProvider() {
|
|
4
|
+
let cachedCredentials = null;
|
|
5
|
+
let forceRefresh = false;
|
|
6
|
+
async function readCurrentCredentials() {
|
|
7
|
+
const config = await loadConfig();
|
|
8
|
+
if (config === null) {
|
|
9
|
+
throw new Error("Not logged in. Run barekey login first.");
|
|
10
|
+
}
|
|
11
|
+
const credentials = await loadCredentials(config.activeAccountId);
|
|
12
|
+
if (credentials === null) {
|
|
13
|
+
throw new Error("CLI credentials are missing. Run barekey login again.");
|
|
14
|
+
}
|
|
15
|
+
cachedCredentials = credentials;
|
|
16
|
+
return {
|
|
17
|
+
baseUrl: config.baseUrl,
|
|
18
|
+
accountId: config.activeAccountId,
|
|
19
|
+
credentials,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function refreshIfNeeded() {
|
|
23
|
+
const { baseUrl, accountId, credentials } = await readCurrentCredentials();
|
|
24
|
+
const now = Date.now();
|
|
25
|
+
if (!forceRefresh && credentials.accessTokenExpiresAtMs > now + 10_000) {
|
|
26
|
+
return credentials;
|
|
27
|
+
}
|
|
28
|
+
const refreshed = await postJson({
|
|
29
|
+
baseUrl,
|
|
30
|
+
path: "/v1/cli/token/refresh",
|
|
31
|
+
payload: {
|
|
32
|
+
refreshToken: credentials.refreshToken,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
const nextCredentials = {
|
|
36
|
+
accessToken: refreshed.accessToken,
|
|
37
|
+
refreshToken: refreshed.refreshToken,
|
|
38
|
+
accessTokenExpiresAtMs: refreshed.accessTokenExpiresAtMs,
|
|
39
|
+
refreshTokenExpiresAtMs: refreshed.refreshTokenExpiresAtMs,
|
|
40
|
+
clerkUserId: refreshed.clerkUserId,
|
|
41
|
+
orgId: refreshed.orgId,
|
|
42
|
+
orgSlug: refreshed.orgSlug,
|
|
43
|
+
};
|
|
44
|
+
await saveCredentials(accountId, nextCredentials);
|
|
45
|
+
cachedCredentials = nextCredentials;
|
|
46
|
+
forceRefresh = false;
|
|
47
|
+
return nextCredentials;
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
async getAccessToken() {
|
|
51
|
+
const credentials = await refreshIfNeeded();
|
|
52
|
+
return credentials.accessToken;
|
|
53
|
+
},
|
|
54
|
+
async onAuthError() {
|
|
55
|
+
forceRefresh = true;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import type { CliCredentials } from "./types.js";
|
|
3
|
+
export type LocalSession = {
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
accountId: string;
|
|
6
|
+
credentials: CliCredentials;
|
|
7
|
+
};
|
|
8
|
+
export type EnvTargetOptions = {
|
|
9
|
+
project?: string;
|
|
10
|
+
stage?: string;
|
|
11
|
+
org?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function toJsonOutput(enabled: boolean, value: unknown): void;
|
|
14
|
+
export declare function resolveBaseUrl(explicit: string | undefined): Promise<string>;
|
|
15
|
+
export declare function requireLocalSession(): Promise<LocalSession>;
|
|
16
|
+
export declare function resolveTarget(options: EnvTargetOptions, local: LocalSession): Promise<{
|
|
17
|
+
projectSlug: string;
|
|
18
|
+
stageSlug: string;
|
|
19
|
+
orgSlug?: string;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function parseChance(value: string | undefined): number;
|
|
22
|
+
export declare function dotenvEscape(value: string): string;
|
|
23
|
+
export declare function addTargetOptions(command: Command): Command;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { loadConfig, loadCredentials } from "./credentials-store.js";
|
|
2
|
+
import { DEFAULT_BAREKEY_API_URL } from "./constants.js";
|
|
3
|
+
import { loadRuntimeConfig } from "./runtime-config.js";
|
|
4
|
+
export function toJsonOutput(enabled, value) {
|
|
5
|
+
if (!enabled) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
console.log(JSON.stringify(value, null, 2));
|
|
9
|
+
}
|
|
10
|
+
export async function resolveBaseUrl(explicit) {
|
|
11
|
+
const explicitUrl = explicit?.trim();
|
|
12
|
+
if (explicitUrl && explicitUrl.length > 0) {
|
|
13
|
+
return explicitUrl.replace(/\/$/, "");
|
|
14
|
+
}
|
|
15
|
+
const envUrl = process.env.BAREKEY_API_URL?.trim();
|
|
16
|
+
if (envUrl && envUrl.length > 0) {
|
|
17
|
+
return envUrl.replace(/\/$/, "");
|
|
18
|
+
}
|
|
19
|
+
const config = await loadConfig();
|
|
20
|
+
if (config && config.baseUrl.length > 0) {
|
|
21
|
+
return config.baseUrl.replace(/\/$/, "");
|
|
22
|
+
}
|
|
23
|
+
return DEFAULT_BAREKEY_API_URL;
|
|
24
|
+
}
|
|
25
|
+
export async function requireLocalSession() {
|
|
26
|
+
const config = await loadConfig();
|
|
27
|
+
if (config === null) {
|
|
28
|
+
throw new Error("Not logged in. Run barekey auth login first.");
|
|
29
|
+
}
|
|
30
|
+
const credentials = await loadCredentials(config.activeAccountId);
|
|
31
|
+
if (credentials === null) {
|
|
32
|
+
throw new Error("Saved credentials not found. Run barekey auth login again.");
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
baseUrl: config.baseUrl,
|
|
36
|
+
accountId: config.activeAccountId,
|
|
37
|
+
credentials,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export async function resolveTarget(options, local) {
|
|
41
|
+
const runtime = await loadRuntimeConfig();
|
|
42
|
+
const projectSlug = options.project?.trim() || runtime?.config.project || "";
|
|
43
|
+
const stageSlug = options.stage?.trim() || runtime?.config.environment || "";
|
|
44
|
+
const orgSlug = options.org?.trim() || runtime?.config.org || local.credentials.orgSlug;
|
|
45
|
+
if (projectSlug.length === 0 || stageSlug.length === 0) {
|
|
46
|
+
const hint = runtime
|
|
47
|
+
? `Found ${runtime.path} but project/environment is incomplete.`
|
|
48
|
+
: "No barekey.json found in current directory tree.";
|
|
49
|
+
throw new Error(`${hint} Pass --project/--stage, or create barekey.json with {"organization":"...","project":"...","environment":"..."}.`);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
projectSlug,
|
|
53
|
+
stageSlug,
|
|
54
|
+
orgSlug: orgSlug.length > 0 ? orgSlug : undefined,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function parseChance(value) {
|
|
58
|
+
if (value === undefined) {
|
|
59
|
+
throw new Error("--chance is required when using --ab.");
|
|
60
|
+
}
|
|
61
|
+
const parsed = Number(value);
|
|
62
|
+
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
|
|
63
|
+
throw new Error("--chance must be a number between 0 and 1.");
|
|
64
|
+
}
|
|
65
|
+
return parsed;
|
|
66
|
+
}
|
|
67
|
+
export function dotenvEscape(value) {
|
|
68
|
+
if (/^[A-Za-z0-9_./:-]+$/.test(value)) {
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
return JSON.stringify(value);
|
|
72
|
+
}
|
|
73
|
+
export function addTargetOptions(command) {
|
|
74
|
+
return command
|
|
75
|
+
.option("--project <slug>", "Project slug")
|
|
76
|
+
.option("--stage <slug>", "Stage slug")
|
|
77
|
+
.option("--org <slug>", "Organization slug");
|
|
78
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import { setTimeout as wait } from "node:timers/promises";
|
|
3
|
+
import { intro, outro, spinner } from "@clack/prompts";
|
|
4
|
+
import pc from "picocolors";
|
|
5
|
+
import open from "open";
|
|
6
|
+
import { createCliAuthProvider } from "../auth-provider.js";
|
|
7
|
+
import { clearConfig, deleteCredentials, saveConfig, saveCredentials, } from "../credentials-store.js";
|
|
8
|
+
import { getJson, postJson } from "../http.js";
|
|
9
|
+
import { requireLocalSession, resolveBaseUrl, toJsonOutput } from "../command-utils.js";
|
|
10
|
+
function resolveClientName() {
|
|
11
|
+
const configured = process.env.BAREKEY_CLIENT_NAME?.trim() ||
|
|
12
|
+
process.env.COMPUTERNAME?.trim() ||
|
|
13
|
+
process.env.HOSTNAME?.trim() ||
|
|
14
|
+
os.hostname().trim();
|
|
15
|
+
if (configured.length === 0) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return configured.slice(0, 120);
|
|
19
|
+
}
|
|
20
|
+
function resolveVerificationUri(baseUrl, verificationUri) {
|
|
21
|
+
try {
|
|
22
|
+
const resolvedBaseUrl = new URL(baseUrl);
|
|
23
|
+
const resolvedVerificationUrl = new URL(verificationUri);
|
|
24
|
+
const isConvexHost = resolvedVerificationUrl.host.endsWith(".convex.site") ||
|
|
25
|
+
resolvedVerificationUrl.host.endsWith(".convex.cloud");
|
|
26
|
+
const usesPublicApiHost = resolvedBaseUrl.host.startsWith("api.");
|
|
27
|
+
if (isConvexHost && usesPublicApiHost) {
|
|
28
|
+
return new URL(`${resolvedVerificationUrl.pathname}${resolvedVerificationUrl.search}`, `${resolvedBaseUrl.protocol}//${resolvedBaseUrl.host.replace(/^api\./, "")}`).toString();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return verificationUri;
|
|
33
|
+
}
|
|
34
|
+
return verificationUri;
|
|
35
|
+
}
|
|
36
|
+
async function runLogin(options) {
|
|
37
|
+
const baseUrl = await resolveBaseUrl(options.baseUrl);
|
|
38
|
+
intro("Barekey CLI login");
|
|
39
|
+
const loading = spinner();
|
|
40
|
+
loading.start("Starting device authorization");
|
|
41
|
+
let loadingActive = true;
|
|
42
|
+
let pollSpinner = null;
|
|
43
|
+
let pollActive = false;
|
|
44
|
+
try {
|
|
45
|
+
const started = await postJson({
|
|
46
|
+
baseUrl,
|
|
47
|
+
path: "/v1/cli/device/start",
|
|
48
|
+
payload: {
|
|
49
|
+
clientName: resolveClientName(),
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const verificationUri = resolveVerificationUri(baseUrl, started.verificationUri);
|
|
53
|
+
loading.stop("Authorization initialized");
|
|
54
|
+
loadingActive = false;
|
|
55
|
+
console.log(`${pc.bold("Open")}: ${verificationUri}`);
|
|
56
|
+
console.log(`${pc.bold("Code")}: ${started.userCode}`);
|
|
57
|
+
try {
|
|
58
|
+
await open(verificationUri);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// Browser-open can fail in headless environments.
|
|
62
|
+
}
|
|
63
|
+
const startedAtMs = Date.now();
|
|
64
|
+
const expiresAtMs = startedAtMs + started.expiresInSec * 1000;
|
|
65
|
+
pollSpinner = spinner();
|
|
66
|
+
pollSpinner.start("Waiting for approval in browser");
|
|
67
|
+
pollActive = true;
|
|
68
|
+
while (Date.now() < expiresAtMs) {
|
|
69
|
+
const poll = await postJson({
|
|
70
|
+
baseUrl,
|
|
71
|
+
path: "/v1/cli/device/poll",
|
|
72
|
+
payload: {
|
|
73
|
+
deviceCode: started.deviceCode,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
if (poll.status === "pending") {
|
|
77
|
+
await wait(Math.max(1, poll.intervalSec) * 1000);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const accountId = `${poll.orgSlug}:${poll.clerkUserId}`;
|
|
81
|
+
await saveCredentials(accountId, {
|
|
82
|
+
accessToken: poll.accessToken,
|
|
83
|
+
refreshToken: poll.refreshToken,
|
|
84
|
+
accessTokenExpiresAtMs: poll.accessTokenExpiresAtMs,
|
|
85
|
+
refreshTokenExpiresAtMs: poll.refreshTokenExpiresAtMs,
|
|
86
|
+
clerkUserId: poll.clerkUserId,
|
|
87
|
+
orgId: poll.orgId,
|
|
88
|
+
orgSlug: poll.orgSlug,
|
|
89
|
+
});
|
|
90
|
+
await saveConfig({
|
|
91
|
+
baseUrl,
|
|
92
|
+
activeAccountId: accountId,
|
|
93
|
+
});
|
|
94
|
+
pollSpinner.stop("Login approved");
|
|
95
|
+
pollActive = false;
|
|
96
|
+
outro(`Logged in as ${pc.bold(poll.clerkUserId)} in ${pc.bold(poll.orgSlug)}.`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
pollSpinner.stop("Timed out");
|
|
100
|
+
pollActive = false;
|
|
101
|
+
throw new Error("Login timed out before device approval completed.");
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (loadingActive) {
|
|
105
|
+
loading.stop("Authorization failed");
|
|
106
|
+
}
|
|
107
|
+
if (pollSpinner && pollActive) {
|
|
108
|
+
pollSpinner.stop("Login failed");
|
|
109
|
+
}
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async function runLogout() {
|
|
114
|
+
const local = await requireLocalSession();
|
|
115
|
+
await postJson({
|
|
116
|
+
baseUrl: local.baseUrl,
|
|
117
|
+
path: "/v1/cli/logout",
|
|
118
|
+
payload: {
|
|
119
|
+
refreshToken: local.credentials.refreshToken,
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
await deleteCredentials(local.accountId);
|
|
123
|
+
await clearConfig();
|
|
124
|
+
console.log("Logged out.");
|
|
125
|
+
}
|
|
126
|
+
async function runWhoami(options) {
|
|
127
|
+
const local = await requireLocalSession();
|
|
128
|
+
const authProvider = createCliAuthProvider();
|
|
129
|
+
const accessToken = await authProvider.getAccessToken();
|
|
130
|
+
const session = await getJson({
|
|
131
|
+
baseUrl: local.baseUrl,
|
|
132
|
+
path: "/v1/cli/session",
|
|
133
|
+
accessToken,
|
|
134
|
+
});
|
|
135
|
+
if (options.json) {
|
|
136
|
+
toJsonOutput(true, session);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
console.log(`${pc.bold("User")}: ${session.clerkUserId}`);
|
|
140
|
+
console.log(`${pc.bold("Org")}: ${session.orgSlug}`);
|
|
141
|
+
console.log(`${pc.bold("Source")}: ${session.source}`);
|
|
142
|
+
}
|
|
143
|
+
export function registerAuthCommands(program) {
|
|
144
|
+
const auth = program.command("auth").description("Authentication commands");
|
|
145
|
+
auth
|
|
146
|
+
.command("login")
|
|
147
|
+
.description("Authenticate this machine using browser device flow")
|
|
148
|
+
.option("--base-url <url>", "Barekey API base URL")
|
|
149
|
+
.action(async (options) => {
|
|
150
|
+
await runLogin(options);
|
|
151
|
+
});
|
|
152
|
+
auth
|
|
153
|
+
.command("logout")
|
|
154
|
+
.description("Revoke local CLI session")
|
|
155
|
+
.action(async () => {
|
|
156
|
+
await runLogout();
|
|
157
|
+
});
|
|
158
|
+
auth
|
|
159
|
+
.command("whoami")
|
|
160
|
+
.description("Show active CLI auth context")
|
|
161
|
+
.option("--json", "Machine-readable output", false)
|
|
162
|
+
.action(async (options) => {
|
|
163
|
+
await runWhoami(options);
|
|
164
|
+
});
|
|
165
|
+
// Backward-compatible top-level auth aliases.
|
|
166
|
+
program
|
|
167
|
+
.command("login")
|
|
168
|
+
.description("Alias for barekey auth login")
|
|
169
|
+
.option("--base-url <url>", "Barekey API base URL")
|
|
170
|
+
.action(async (options) => {
|
|
171
|
+
await runLogin(options);
|
|
172
|
+
});
|
|
173
|
+
program
|
|
174
|
+
.command("logout")
|
|
175
|
+
.description("Alias for barekey auth logout")
|
|
176
|
+
.action(async () => {
|
|
177
|
+
await runLogout();
|
|
178
|
+
});
|
|
179
|
+
program
|
|
180
|
+
.command("whoami")
|
|
181
|
+
.description("Alias for barekey auth whoami")
|
|
182
|
+
.option("--json", "Machine-readable output", false)
|
|
183
|
+
.action(async (options) => {
|
|
184
|
+
await runWhoami(options);
|
|
185
|
+
});
|
|
186
|
+
}
|