@barekey/cli 0.4.0 → 0.5.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/README.md +53 -12
- package/bun.lock +9 -3
- package/dist/auth-provider.js +7 -4
- package/dist/command-utils.js +6 -6
- package/dist/commands/audit.d.ts +2 -0
- package/dist/commands/audit.js +47 -0
- package/dist/commands/auth.js +22 -7
- package/dist/commands/billing.d.ts +2 -0
- package/dist/commands/billing.js +62 -0
- package/dist/commands/env.js +157 -125
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +32 -0
- package/dist/commands/org.d.ts +2 -0
- package/dist/commands/org.js +85 -0
- package/dist/commands/project.d.ts +2 -0
- package/dist/commands/project.js +99 -0
- package/dist/commands/stage.d.ts +2 -0
- package/dist/commands/stage.js +125 -0
- package/dist/commands/target-prompts.d.ts +184 -0
- package/dist/commands/target-prompts.js +312 -0
- package/dist/commands/typegen.d.ts +2 -2
- package/dist/commands/typegen.js +57 -32
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/context/session-id.d.ts +11 -0
- package/dist/context/session-id.js +14 -0
- package/dist/contracts/index.d.ts +491 -0
- package/dist/contracts/index.js +307 -0
- package/dist/credentials-store.js +70 -11
- package/dist/http.d.ts +34 -0
- package/dist/http.js +56 -2
- package/dist/index.js +12 -0
- package/dist/runtime-config.js +14 -26
- package/dist/typegen/core.d.ts +45 -0
- package/dist/typegen/core.js +219 -0
- package/dist/types.d.ts +5 -3
- package/package.json +2 -2
- package/src/auth-provider.ts +8 -5
- package/src/command-utils.ts +6 -6
- package/src/commands/audit.ts +63 -0
- package/src/commands/auth.ts +32 -37
- package/src/commands/billing.ts +73 -0
- package/src/commands/env.ts +211 -218
- package/src/commands/init.ts +47 -0
- package/src/commands/org.ts +104 -0
- package/src/commands/project.ts +130 -0
- package/src/commands/stage.ts +167 -0
- package/src/commands/target-prompts.ts +357 -0
- package/src/commands/typegen.ts +71 -45
- package/src/constants.ts +1 -1
- package/src/context/session-id.ts +14 -0
- package/src/contracts/index.ts +370 -0
- package/src/credentials-store.ts +86 -12
- package/src/http.ts +78 -2
- package/src/index.ts +12 -0
- package/src/runtime-config.ts +19 -32
- package/src/typegen/core.ts +311 -0
- package/src/types.ts +5 -3
- package/test/command-utils.test.ts +47 -0
- package/test/credentials-store.test.ts +40 -0
package/README.md
CHANGED
|
@@ -1,34 +1,75 @@
|
|
|
1
1
|
# @barekey/cli
|
|
2
2
|
|
|
3
|
-
CLI for
|
|
3
|
+
CLI for Barekey login, variable management, pull workflows, and SDK type generation.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
npm install -g @barekey/cli
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quickstart
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
barekey auth login
|
|
15
|
-
barekey
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
barekey auth whoami
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Create `barekey.json`:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"organization": "acme",
|
|
23
|
+
"project": "web",
|
|
24
|
+
"environment": "development"
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Create and read a variable:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
barekey env new DATABASE_URL "postgres://localhost:5432/app" --type string
|
|
32
|
+
barekey env get DATABASE_URL
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Update it:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
barekey env set DATABASE_URL "postgres://localhost:5432/app_v2"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Pull local files:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
barekey env pull --out .env.local
|
|
45
|
+
barekey env pull --format json --out barekey.local.json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Generate SDK types:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
barekey typegen
|
|
52
|
+
barekey typegen --watch
|
|
18
53
|
```
|
|
19
54
|
|
|
20
55
|
## Common commands
|
|
21
56
|
|
|
22
57
|
```bash
|
|
23
|
-
barekey
|
|
24
|
-
barekey env
|
|
25
|
-
barekey env
|
|
26
|
-
barekey env
|
|
27
|
-
barekey env
|
|
28
|
-
barekey
|
|
29
|
-
barekey typegen --watch --org acme --project api --stage development
|
|
58
|
+
barekey env list
|
|
59
|
+
barekey env get-many --names DATABASE_URL,REDIS_URL
|
|
60
|
+
barekey env new FEATURE_ENABLED true --type boolean
|
|
61
|
+
barekey env set PUBLIC_TITLE "Barekey Docs" --visibility public
|
|
62
|
+
barekey env set CHECKOUT_FLOW control --ab treatment --chance 0.5
|
|
63
|
+
barekey env delete FEATURE_ENABLED --yes
|
|
30
64
|
```
|
|
31
65
|
|
|
66
|
+
## Notes
|
|
67
|
+
|
|
68
|
+
- `env new` creates with an initial value.
|
|
69
|
+
- `env set` is the upsert command.
|
|
70
|
+
- `get-many` uses a comma-separated `--names` value.
|
|
71
|
+
- Target resolution comes from flags, `barekey.json`, and the stored login org.
|
|
72
|
+
|
|
32
73
|
## Development
|
|
33
74
|
|
|
34
75
|
```bash
|
package/bun.lock
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
"": {
|
|
6
6
|
"name": "@barekey/cli",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@barekey/sdk": "^0.5.0",
|
|
9
8
|
"@clack/prompts": "^0.11.0",
|
|
10
9
|
"commander": "^14.0.1",
|
|
10
|
+
"effect": "3.19.19",
|
|
11
11
|
"open": "^10.2.0",
|
|
12
12
|
"picocolors": "^1.1.1",
|
|
13
13
|
},
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
20
|
"packages": {
|
|
21
|
-
"@barekey/sdk": ["@barekey/sdk@0.5.0", "", {}, "sha512-+8RoKix9DZee3ZheGP5wJLnet6XaEGHTfcJOuvtJLmfQKRBllUy+wevsvELi1wOjw42pWaG3DYyb68XHznZRQw=="],
|
|
22
|
-
|
|
23
21
|
"@clack/core": ["@clack/core@0.5.0", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow=="],
|
|
24
22
|
|
|
25
23
|
"@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="],
|
|
26
24
|
|
|
25
|
+
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
|
26
|
+
|
|
27
27
|
"@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
|
28
28
|
|
|
29
29
|
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
|
|
37
37
|
"define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
|
|
38
38
|
|
|
39
|
+
"effect": ["effect@3.19.19", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-Yc8U/SVXo2dHnaP7zNBlAo83h/nzSJpi7vph6Hzyl4ulgMBIgPmz3UzOjb9sBgpFE00gC0iETR244sfXDNLHRg=="],
|
|
40
|
+
|
|
41
|
+
"fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="],
|
|
42
|
+
|
|
39
43
|
"is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
|
|
40
44
|
|
|
41
45
|
"is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
|
|
@@ -46,6 +50,8 @@
|
|
|
46
50
|
|
|
47
51
|
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
48
52
|
|
|
53
|
+
"pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
|
|
54
|
+
|
|
49
55
|
"run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],
|
|
50
56
|
|
|
51
57
|
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
package/dist/auth-provider.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { postJson } from "./http.js";
|
|
2
2
|
import { loadConfig, loadCredentials, saveCredentials } from "./credentials-store.js";
|
|
3
|
+
import { buildSessionId } from "./context/session-id.js";
|
|
3
4
|
export function createCliAuthProvider() {
|
|
4
5
|
let cachedCredentials = null;
|
|
5
6
|
let forceRefresh = false;
|
|
@@ -8,19 +9,19 @@ export function createCliAuthProvider() {
|
|
|
8
9
|
if (config === null) {
|
|
9
10
|
throw new Error("Not logged in. Run barekey login first.");
|
|
10
11
|
}
|
|
11
|
-
const credentials = await loadCredentials(config.
|
|
12
|
+
const credentials = await loadCredentials(config.activeSessionId);
|
|
12
13
|
if (credentials === null) {
|
|
13
14
|
throw new Error("CLI credentials are missing. Run barekey login again.");
|
|
14
15
|
}
|
|
15
16
|
cachedCredentials = credentials;
|
|
16
17
|
return {
|
|
17
18
|
baseUrl: config.baseUrl,
|
|
18
|
-
|
|
19
|
+
sessionId: config.activeSessionId,
|
|
19
20
|
credentials,
|
|
20
21
|
};
|
|
21
22
|
}
|
|
22
23
|
async function refreshIfNeeded() {
|
|
23
|
-
const { baseUrl,
|
|
24
|
+
const { baseUrl, credentials } = await readCurrentCredentials();
|
|
24
25
|
const now = Date.now();
|
|
25
26
|
if (!forceRefresh && credentials.accessTokenExpiresAtMs > now + 10_000) {
|
|
26
27
|
return credentials;
|
|
@@ -40,8 +41,10 @@ export function createCliAuthProvider() {
|
|
|
40
41
|
clerkUserId: refreshed.clerkUserId,
|
|
41
42
|
orgId: refreshed.orgId,
|
|
42
43
|
orgSlug: refreshed.orgSlug,
|
|
44
|
+
lastOrgId: refreshed.orgId,
|
|
45
|
+
lastOrgSlug: refreshed.orgSlug,
|
|
43
46
|
};
|
|
44
|
-
await saveCredentials(
|
|
47
|
+
await saveCredentials(buildSessionId(baseUrl, refreshed.clerkUserId), nextCredentials);
|
|
45
48
|
cachedCredentials = nextCredentials;
|
|
46
49
|
forceRefresh = false;
|
|
47
50
|
return nextCredentials;
|
package/dist/command-utils.js
CHANGED
|
@@ -27,13 +27,13 @@ export async function requireLocalSession() {
|
|
|
27
27
|
if (config === null) {
|
|
28
28
|
throw new Error("Not logged in. Run barekey auth login first.");
|
|
29
29
|
}
|
|
30
|
-
const credentials = await loadCredentials(config.
|
|
30
|
+
const credentials = await loadCredentials(config.activeSessionId);
|
|
31
31
|
if (credentials === null) {
|
|
32
32
|
throw new Error("Saved credentials not found. Run barekey auth login again.");
|
|
33
33
|
}
|
|
34
34
|
return {
|
|
35
35
|
baseUrl: config.baseUrl,
|
|
36
|
-
accountId: config.
|
|
36
|
+
accountId: config.activeSessionId,
|
|
37
37
|
credentials,
|
|
38
38
|
};
|
|
39
39
|
}
|
|
@@ -42,12 +42,12 @@ export async function resolveTarget(options, local) {
|
|
|
42
42
|
const isStandalone = runtime?.config.config?.mode === "standalone";
|
|
43
43
|
const projectSlug = options.project?.trim() || runtime?.config.project || "";
|
|
44
44
|
const stageSlug = options.stage?.trim() || runtime?.config.environment || "";
|
|
45
|
-
const orgSlug = options.org?.trim() || runtime?.config.org ||
|
|
46
|
-
if (!isStandalone && (projectSlug.length === 0 || stageSlug.length === 0)) {
|
|
45
|
+
const orgSlug = options.org?.trim() || runtime?.config.org || "";
|
|
46
|
+
if (!isStandalone && (orgSlug.length === 0 || projectSlug.length === 0 || stageSlug.length === 0)) {
|
|
47
47
|
const hint = runtime
|
|
48
|
-
? `Found ${runtime.path} but project/environment is incomplete.`
|
|
48
|
+
? `Found ${runtime.path} but organization/project/environment is incomplete.`
|
|
49
49
|
: "No barekey.json found in current directory tree.";
|
|
50
|
-
throw new Error(`${hint}
|
|
50
|
+
throw new Error(`${hint} Run barekey init or pass --org/--project/--stage.`);
|
|
51
51
|
}
|
|
52
52
|
return {
|
|
53
53
|
projectSlug,
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createCliAuthProvider } from "../auth-provider.js";
|
|
2
|
+
import { requireLocalSession, toJsonOutput } from "../command-utils.js";
|
|
3
|
+
import { AuditListResponseSchema } from "../contracts/index.js";
|
|
4
|
+
import { postJson } from "../http.js";
|
|
5
|
+
import { promptForOrganizationSlug } from "./target-prompts.js";
|
|
6
|
+
async function runAuditList(options) {
|
|
7
|
+
const local = await requireLocalSession();
|
|
8
|
+
const authProvider = createCliAuthProvider();
|
|
9
|
+
const accessToken = await authProvider.getAccessToken();
|
|
10
|
+
const orgSlug = await promptForOrganizationSlug(options.org);
|
|
11
|
+
const limit = options.limit ? Number.parseInt(options.limit, 10) : 25;
|
|
12
|
+
const response = await postJson({
|
|
13
|
+
baseUrl: local.baseUrl,
|
|
14
|
+
path: "/v1/cli/audit/list",
|
|
15
|
+
accessToken,
|
|
16
|
+
payload: {
|
|
17
|
+
orgSlug,
|
|
18
|
+
projectSlug: options.project?.trim() || null,
|
|
19
|
+
limit: Number.isFinite(limit) ? limit : 25,
|
|
20
|
+
},
|
|
21
|
+
schema: AuditListResponseSchema,
|
|
22
|
+
});
|
|
23
|
+
if (options.json) {
|
|
24
|
+
toJsonOutput(true, response);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (response.items.length === 0) {
|
|
28
|
+
console.log("No audit events found.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
for (const item of response.items) {
|
|
32
|
+
console.log(`${new Date(item.occurredAtMs).toISOString()} ${item.category} ${item.title}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function registerAuditCommands(program) {
|
|
36
|
+
const audit = program.command("audit").description("Audit history");
|
|
37
|
+
audit
|
|
38
|
+
.command("list")
|
|
39
|
+
.description("List recent audit events")
|
|
40
|
+
.option("--org <slug>", "Organization slug")
|
|
41
|
+
.option("--project <slug>", "Project slug")
|
|
42
|
+
.option("--limit <count>", "Maximum number of events", "25")
|
|
43
|
+
.option("--json", "Machine-readable output", false)
|
|
44
|
+
.action(async (options) => {
|
|
45
|
+
await runAuditList(options);
|
|
46
|
+
});
|
|
47
|
+
}
|
package/dist/commands/auth.js
CHANGED
|
@@ -4,7 +4,9 @@ import { intro, outro, spinner } from "@clack/prompts";
|
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
import open from "open";
|
|
6
6
|
import { createCliAuthProvider } from "../auth-provider.js";
|
|
7
|
+
import { buildSessionId } from "../context/session-id.js";
|
|
7
8
|
import { clearConfig, deleteCredentials, saveConfig, saveCredentials, } from "../credentials-store.js";
|
|
9
|
+
import { CliSessionResponseSchema, DevicePollResponseSchema, DeviceStartResponseSchema, RefreshResponseSchema, } from "../contracts/index.js";
|
|
8
10
|
import { getJson, postJson } from "../http.js";
|
|
9
11
|
import { requireLocalSession, resolveBaseUrl, toJsonOutput } from "../command-utils.js";
|
|
10
12
|
function resolveClientName() {
|
|
@@ -48,6 +50,7 @@ async function runLogin(options) {
|
|
|
48
50
|
payload: {
|
|
49
51
|
clientName: resolveClientName(),
|
|
50
52
|
},
|
|
53
|
+
schema: DeviceStartResponseSchema,
|
|
51
54
|
});
|
|
52
55
|
const verificationUri = resolveVerificationUri(baseUrl, started.verificationUri);
|
|
53
56
|
loading.stop("Authorization initialized");
|
|
@@ -72,28 +75,40 @@ async function runLogin(options) {
|
|
|
72
75
|
payload: {
|
|
73
76
|
deviceCode: started.deviceCode,
|
|
74
77
|
},
|
|
78
|
+
schema: DevicePollResponseSchema,
|
|
75
79
|
});
|
|
76
80
|
if (poll.status === "pending") {
|
|
77
81
|
await wait(Math.max(1, poll.intervalSec) * 1000);
|
|
78
82
|
continue;
|
|
79
83
|
}
|
|
80
|
-
const
|
|
81
|
-
await saveCredentials(accountId, {
|
|
84
|
+
const refreshed = RefreshResponseSchema.make({
|
|
82
85
|
accessToken: poll.accessToken,
|
|
83
86
|
refreshToken: poll.refreshToken,
|
|
84
87
|
accessTokenExpiresAtMs: poll.accessTokenExpiresAtMs,
|
|
85
88
|
refreshTokenExpiresAtMs: poll.refreshTokenExpiresAtMs,
|
|
86
|
-
clerkUserId: poll.clerkUserId,
|
|
87
89
|
orgId: poll.orgId,
|
|
88
90
|
orgSlug: poll.orgSlug,
|
|
91
|
+
clerkUserId: poll.clerkUserId,
|
|
92
|
+
});
|
|
93
|
+
const sessionId = buildSessionId(baseUrl, refreshed.clerkUserId);
|
|
94
|
+
await saveCredentials(sessionId, {
|
|
95
|
+
accessToken: refreshed.accessToken,
|
|
96
|
+
refreshToken: refreshed.refreshToken,
|
|
97
|
+
accessTokenExpiresAtMs: refreshed.accessTokenExpiresAtMs,
|
|
98
|
+
refreshTokenExpiresAtMs: refreshed.refreshTokenExpiresAtMs,
|
|
99
|
+
clerkUserId: refreshed.clerkUserId,
|
|
100
|
+
orgId: refreshed.orgId,
|
|
101
|
+
orgSlug: refreshed.orgSlug,
|
|
102
|
+
lastOrgId: refreshed.orgId,
|
|
103
|
+
lastOrgSlug: refreshed.orgSlug,
|
|
89
104
|
});
|
|
90
105
|
await saveConfig({
|
|
91
106
|
baseUrl,
|
|
92
|
-
|
|
107
|
+
activeSessionId: sessionId,
|
|
93
108
|
});
|
|
94
109
|
pollSpinner.stop("Login approved");
|
|
95
110
|
pollActive = false;
|
|
96
|
-
outro(`Logged in as ${pc.bold(
|
|
111
|
+
outro(`Logged in as ${pc.bold(refreshed.clerkUserId)}.`);
|
|
97
112
|
return;
|
|
98
113
|
}
|
|
99
114
|
pollSpinner.stop("Timed out");
|
|
@@ -131,13 +146,14 @@ async function runWhoami(options) {
|
|
|
131
146
|
baseUrl: local.baseUrl,
|
|
132
147
|
path: "/v1/cli/session",
|
|
133
148
|
accessToken,
|
|
149
|
+
schema: CliSessionResponseSchema,
|
|
134
150
|
});
|
|
135
151
|
if (options.json) {
|
|
136
152
|
toJsonOutput(true, session);
|
|
137
153
|
return;
|
|
138
154
|
}
|
|
139
155
|
console.log(`${pc.bold("User")}: ${session.clerkUserId}`);
|
|
140
|
-
console.log(`${pc.bold("
|
|
156
|
+
console.log(`${pc.bold("Current org")}: ${session.orgSlug}`);
|
|
141
157
|
console.log(`${pc.bold("Source")}: ${session.source}`);
|
|
142
158
|
}
|
|
143
159
|
export function registerAuthCommands(program) {
|
|
@@ -162,7 +178,6 @@ export function registerAuthCommands(program) {
|
|
|
162
178
|
.action(async (options) => {
|
|
163
179
|
await runWhoami(options);
|
|
164
180
|
});
|
|
165
|
-
// Backward-compatible top-level auth aliases.
|
|
166
181
|
program
|
|
167
182
|
.command("login")
|
|
168
183
|
.description("Alias for barekey auth login")
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createCliAuthProvider } from "../auth-provider.js";
|
|
2
|
+
import { requireLocalSession, toJsonOutput } from "../command-utils.js";
|
|
3
|
+
import { BillingCatalogResponseSchema, BillingStatusResponseSchema } from "../contracts/index.js";
|
|
4
|
+
import { getJson, postJson } from "../http.js";
|
|
5
|
+
import { promptForOrganizationSlug } from "./target-prompts.js";
|
|
6
|
+
async function runBillingCatalog(options) {
|
|
7
|
+
const local = await requireLocalSession();
|
|
8
|
+
const authProvider = createCliAuthProvider();
|
|
9
|
+
const accessToken = await authProvider.getAccessToken();
|
|
10
|
+
const response = await getJson({
|
|
11
|
+
baseUrl: local.baseUrl,
|
|
12
|
+
path: "/v1/cli/billing/catalog",
|
|
13
|
+
accessToken,
|
|
14
|
+
schema: BillingCatalogResponseSchema,
|
|
15
|
+
});
|
|
16
|
+
if (options.json) {
|
|
17
|
+
toJsonOutput(true, response);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
console.log(`Plans: ${response.variants.length}`);
|
|
21
|
+
console.log(`Metered features: ${Object.values(response.featureIds).join(", ")}`);
|
|
22
|
+
}
|
|
23
|
+
async function runBillingStatus(options) {
|
|
24
|
+
const local = await requireLocalSession();
|
|
25
|
+
const authProvider = createCliAuthProvider();
|
|
26
|
+
const accessToken = await authProvider.getAccessToken();
|
|
27
|
+
const orgSlug = await promptForOrganizationSlug(options.org);
|
|
28
|
+
const response = await postJson({
|
|
29
|
+
baseUrl: local.baseUrl,
|
|
30
|
+
path: "/v1/cli/billing/status",
|
|
31
|
+
accessToken,
|
|
32
|
+
payload: {
|
|
33
|
+
orgSlug,
|
|
34
|
+
},
|
|
35
|
+
schema: BillingStatusResponseSchema,
|
|
36
|
+
});
|
|
37
|
+
if (options.json) {
|
|
38
|
+
toJsonOutput(true, response);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
console.log(`Tier: ${response.currentTier ?? "none"}`);
|
|
42
|
+
console.log(`Product: ${response.currentProductId ?? "none"}`);
|
|
43
|
+
console.log(`Can manage billing: ${response.canManageBilling ? "yes" : "no"}`);
|
|
44
|
+
}
|
|
45
|
+
export function registerBillingCommands(program) {
|
|
46
|
+
const billing = program.command("billing").description("Billing information");
|
|
47
|
+
billing
|
|
48
|
+
.command("catalog")
|
|
49
|
+
.description("Show the public billing catalog")
|
|
50
|
+
.option("--json", "Machine-readable output", false)
|
|
51
|
+
.action(async (options) => {
|
|
52
|
+
await runBillingCatalog(options);
|
|
53
|
+
});
|
|
54
|
+
billing
|
|
55
|
+
.command("status")
|
|
56
|
+
.description("Show billing status for an organization")
|
|
57
|
+
.option("--org <slug>", "Organization slug")
|
|
58
|
+
.option("--json", "Machine-readable output", false)
|
|
59
|
+
.action(async (options) => {
|
|
60
|
+
await runBillingStatus(options);
|
|
61
|
+
});
|
|
62
|
+
}
|