@nebulr-group/bridge-cli 0.1.0-beta.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +75 -18
- package/dist/auth/api-client.d.ts +48 -0
- package/dist/auth/api-client.d.ts.map +1 -0
- package/dist/auth/api-client.js +109 -0
- package/dist/auth/api-client.js.map +1 -0
- package/dist/auth/browser-open.d.ts +12 -0
- package/dist/auth/browser-open.d.ts.map +1 -0
- package/dist/auth/browser-open.js +82 -0
- package/dist/auth/browser-open.js.map +1 -0
- package/dist/auth/loopback.d.ts +63 -0
- package/dist/auth/loopback.d.ts.map +1 -0
- package/dist/auth/loopback.js +290 -0
- package/dist/auth/loopback.js.map +1 -0
- package/dist/auth/pkce.d.ts +19 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +46 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/auth/relative-time.d.ts +2 -0
- package/dist/auth/relative-time.d.ts.map +1 -0
- package/dist/auth/relative-time.js +27 -0
- package/dist/auth/relative-time.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +9 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/auth/config.command.d.ts +8 -0
- package/dist/commands/auth/config.command.d.ts.map +1 -0
- package/dist/commands/auth/config.command.js +60 -0
- package/dist/commands/auth/config.command.js.map +1 -0
- package/dist/commands/auth/login.command.d.ts +20 -0
- package/dist/commands/auth/login.command.d.ts.map +1 -0
- package/dist/commands/auth/login.command.js +141 -0
- package/dist/commands/auth/login.command.js.map +1 -0
- package/dist/commands/auth/logout.command.d.ts +14 -0
- package/dist/commands/auth/logout.command.d.ts.map +1 -0
- package/dist/commands/auth/logout.command.js +57 -0
- package/dist/commands/auth/logout.command.js.map +1 -0
- package/dist/commands/auth/status.command.d.ts +14 -0
- package/dist/commands/auth/status.command.d.ts.map +1 -0
- package/dist/commands/auth/status.command.js +59 -0
- package/dist/commands/auth/status.command.js.map +1 -0
- package/dist/commands/auth.command.d.ts +10 -1
- package/dist/commands/auth.command.d.ts.map +1 -1
- package/dist/commands/auth.command.js +13 -55
- package/dist/commands/auth.command.js.map +1 -1
- package/dist/commands/guide.command.js +5 -5
- package/dist/commands/guide.command.js.map +1 -1
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +79 -9
- package/dist/config.js.map +1 -1
- package/dist/credentials.d.ts +57 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +136 -0
- package/dist/credentials.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { writeCredentials } from '../../credentials.js';
|
|
2
|
+
import { resetManagementClient } from '../../config.js';
|
|
3
|
+
import { generateCodeVerifier, codeChallengeFor, generateState } from '../../auth/pkce.js';
|
|
4
|
+
import { startLoopback, LoopbackError } from '../../auth/loopback.js';
|
|
5
|
+
import { openBrowser } from '../../auth/browser-open.js';
|
|
6
|
+
import { createCliApiClient, CliAuthApiError } from '../../auth/api-client.js';
|
|
7
|
+
const DEFAULT_API_BASE_URL = 'https://api.thebridge.dev';
|
|
8
|
+
const DEFAULT_AUTH_BASE_URL = 'https://auth.thebridge.dev';
|
|
9
|
+
export function registerAuthLoginCommand(auth) {
|
|
10
|
+
auth
|
|
11
|
+
.command('login')
|
|
12
|
+
.description('Authenticate via browser (loopback PKCE) and save credentials')
|
|
13
|
+
.option('--app <id|name>', 'Pin to a specific app (skips the picker on the consent screen)')
|
|
14
|
+
.option('--label <text>', 'Friendly label stored on the token (default: "bridge-cli")')
|
|
15
|
+
.option('--no-browser', 'Print the authorization URL instead of opening a browser')
|
|
16
|
+
.action(async (opts) => {
|
|
17
|
+
try {
|
|
18
|
+
await runLogin(opts);
|
|
19
|
+
process.exitCode = 0;
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
// Friendly, single-line stderr — never log JWTs / verifiers.
|
|
23
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
24
|
+
process.stderr.write(`bridge auth login: ${msg}\n`);
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async function runLogin(opts) {
|
|
30
|
+
const apiBaseUrl = (process.env.BRIDGE_BASE_URL?.trim() || DEFAULT_API_BASE_URL).replace(/\/$/, '');
|
|
31
|
+
const authBaseUrl = (process.env.BRIDGE_AUTH_BASE_URL?.trim() || DEFAULT_AUTH_BASE_URL).replace(/\/$/, '');
|
|
32
|
+
// 1. PKCE + state.
|
|
33
|
+
const codeVerifier = generateCodeVerifier();
|
|
34
|
+
const codeChallenge = codeChallengeFor(codeVerifier);
|
|
35
|
+
const state = generateState();
|
|
36
|
+
// 2. Boot the single-shot loopback listener.
|
|
37
|
+
let loopback;
|
|
38
|
+
try {
|
|
39
|
+
loopback = await startLoopback({
|
|
40
|
+
expectedState: state,
|
|
41
|
+
// Bounce the browser to a branded success page on cloud-views instead
|
|
42
|
+
// of leaving the user staring at 127.0.0.1.
|
|
43
|
+
successRedirectUrl: `${authBaseUrl}/cli/login-complete`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
throw new Error(`Could not bind a loopback port: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
48
|
+
'Try `bridge auth login --device` once TBP-108 lands, or check whether your firewall blocks 127.0.0.1.');
|
|
49
|
+
}
|
|
50
|
+
const authorizeUrl = buildAuthorizeUrl(authBaseUrl, {
|
|
51
|
+
challenge: codeChallenge,
|
|
52
|
+
redirect: loopback.redirectUri,
|
|
53
|
+
state,
|
|
54
|
+
appId: opts.app,
|
|
55
|
+
label: opts.label,
|
|
56
|
+
});
|
|
57
|
+
// 3. Open browser (or print URL if --no-browser or open fails).
|
|
58
|
+
const stdout = process.stdout;
|
|
59
|
+
// commander's `--no-browser` sets opts.browser === false. Treat unset as the
|
|
60
|
+
// default (open browser); only skip when explicitly false.
|
|
61
|
+
const useBrowser = opts.browser !== false;
|
|
62
|
+
if (!useBrowser) {
|
|
63
|
+
stdout.write(`Open this URL in your browser to continue:\n ${authorizeUrl}\n`);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const open = await openBrowser(authorizeUrl);
|
|
67
|
+
if (!open.ok) {
|
|
68
|
+
stdout.write(`Could not open a browser automatically (${open.reason ?? 'unknown'}). ` +
|
|
69
|
+
`Open this URL manually:\n ${authorizeUrl}\n`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
stdout.write('Opened your browser. Waiting for authorization...\n');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// 4. Await the callback. Translate cancel/CSRF/timeout into friendly errors.
|
|
76
|
+
let result;
|
|
77
|
+
try {
|
|
78
|
+
result = await loopback.result;
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
if (err instanceof LoopbackError) {
|
|
82
|
+
throw new Error(err.message);
|
|
83
|
+
}
|
|
84
|
+
throw err;
|
|
85
|
+
}
|
|
86
|
+
// 5. Exchange the code for a JWT.
|
|
87
|
+
const api = createCliApiClient({ baseUrl: apiBaseUrl });
|
|
88
|
+
let exchanged;
|
|
89
|
+
try {
|
|
90
|
+
exchanged = await api.exchangeCode({
|
|
91
|
+
code: result.code,
|
|
92
|
+
codeVerifier,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
if (err instanceof CliAuthApiError) {
|
|
97
|
+
throw new Error(err.message);
|
|
98
|
+
}
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
// 6. Persist credentials with mode 0600.
|
|
102
|
+
const issuedAt = new Date().toISOString();
|
|
103
|
+
const stored = {
|
|
104
|
+
apiKey: exchanged.api_token,
|
|
105
|
+
expiresAt: exchanged.expires_at,
|
|
106
|
+
issuedAt,
|
|
107
|
+
app: { id: exchanged.app.id, name: exchanged.app.name },
|
|
108
|
+
user: { id: exchanged.user.id, email: exchanged.user.email },
|
|
109
|
+
baseUrl: apiBaseUrl,
|
|
110
|
+
...(opts.label ? { label: opts.label } : {}),
|
|
111
|
+
};
|
|
112
|
+
writeCredentials(stored);
|
|
113
|
+
// Reset the cached BridgeManagement client so the next command picks up the
|
|
114
|
+
// new token (relevant when `auth login` is called within the same process).
|
|
115
|
+
resetManagementClient();
|
|
116
|
+
// 7. Friendly confirmation.
|
|
117
|
+
const expiryHuman = formatExpiryDate(exchanged.expires_at);
|
|
118
|
+
stdout.write(`Logged in as ${exchanged.user.email}. App: ${exchanged.app.name}. Token valid until ${expiryHuman}.\n`);
|
|
119
|
+
}
|
|
120
|
+
function buildAuthorizeUrl(authBaseUrl, params) {
|
|
121
|
+
const url = new URL(`${authBaseUrl}/cli/authorize`);
|
|
122
|
+
url.searchParams.set('challenge', params.challenge);
|
|
123
|
+
url.searchParams.set('redirect', params.redirect);
|
|
124
|
+
url.searchParams.set('state', params.state);
|
|
125
|
+
url.searchParams.set('scope', 'management');
|
|
126
|
+
if (params.appId)
|
|
127
|
+
url.searchParams.set('app_id', params.appId);
|
|
128
|
+
if (params.label)
|
|
129
|
+
url.searchParams.set('label', params.label);
|
|
130
|
+
return url.toString();
|
|
131
|
+
}
|
|
132
|
+
function formatExpiryDate(iso) {
|
|
133
|
+
const d = new Date(iso);
|
|
134
|
+
if (Number.isNaN(d.getTime()))
|
|
135
|
+
return iso;
|
|
136
|
+
// YYYY-MM-DD HH:MM (local) — easier to glance at than a full ISO.
|
|
137
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
138
|
+
return (`${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` +
|
|
139
|
+
`${pad(d.getHours())}:${pad(d.getMinutes())}`);
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=login.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.command.js","sourceRoot":"","sources":["../../../src/commands/auth/login.command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bridge auth logout` — best-effort revoke + delete credentials file.
|
|
3
|
+
*
|
|
4
|
+
* Behavior:
|
|
5
|
+
* - No credentials file → "Not logged in." (exit 0).
|
|
6
|
+
* - File present → call `POST /v1/auth/cli/revoke` with `x-api-key`,
|
|
7
|
+
* treat 401 as success (token already gone), then
|
|
8
|
+
* delete the file. Network errors → warn but still
|
|
9
|
+
* delete (the local file is the source of truth for
|
|
10
|
+
* "logged in" on this machine).
|
|
11
|
+
*/
|
|
12
|
+
import type { Command } from 'commander';
|
|
13
|
+
export declare function registerAuthLogoutCommand(auth: Command): void;
|
|
14
|
+
//# sourceMappingURL=logout.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.command.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/logout.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAc7D"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { credentialsPath, deleteCredentials, readCredentials } from '../../credentials.js';
|
|
2
|
+
import { resetManagementClient } from '../../config.js';
|
|
3
|
+
import { createCliApiClient, CliAuthApiError } from '../../auth/api-client.js';
|
|
4
|
+
export function registerAuthLogoutCommand(auth) {
|
|
5
|
+
auth
|
|
6
|
+
.command('logout')
|
|
7
|
+
.description('Revoke the saved CLI token and delete local credentials')
|
|
8
|
+
.action(async () => {
|
|
9
|
+
try {
|
|
10
|
+
await runLogout();
|
|
11
|
+
process.exitCode = 0;
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
15
|
+
process.stderr.write(`bridge auth logout: ${msg}\n`);
|
|
16
|
+
process.exitCode = 1;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
async function runLogout() {
|
|
21
|
+
const stdout = process.stdout;
|
|
22
|
+
const stderr = process.stderr;
|
|
23
|
+
let creds;
|
|
24
|
+
try {
|
|
25
|
+
creds = readCredentials();
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
// Malformed credentials file — still try to delete it so the user gets unstuck.
|
|
29
|
+
stderr.write(`Warning: existing credentials file at ${credentialsPath()} could not be parsed (${err instanceof Error ? err.message : String(err)}). Removing it.\n`);
|
|
30
|
+
deleteCredentials();
|
|
31
|
+
stdout.write('Logged out (credentials file removed).\n');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!creds) {
|
|
35
|
+
stdout.write('Not logged in.\n');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const api = createCliApiClient({ baseUrl: creds.baseUrl });
|
|
39
|
+
try {
|
|
40
|
+
await api.revokeToken(creds.apiKey);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
// Network failure — warn but still proceed with local deletion.
|
|
44
|
+
if (err instanceof CliAuthApiError && err.code === 'network_error') {
|
|
45
|
+
stderr.write(`Warning: could not reach bridge-api to revoke server-side (${err.message}). Removing local credentials anyway.\n`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// Any other API error is also non-fatal for the local cleanup, but we
|
|
49
|
+
// surface it so the user knows the server-side revoke didn't happen.
|
|
50
|
+
stderr.write(`Warning: server-side revoke returned an error (${err instanceof Error ? err.message : String(err)}). Removing local credentials anyway.\n`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
deleteCredentials();
|
|
54
|
+
resetManagementClient();
|
|
55
|
+
stdout.write(`Logged out ${creds.user.email}.\n`);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=logout.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.command.js","sourceRoot":"","sources":["../../../src/commands/auth/logout.command.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE/E,MAAM,UAAU,yBAAyB,CAAC,IAAa;IACrD,IAAI;SACD,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,yDAAyD,CAAC;SACtE,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,SAAS,EAAE,CAAC;YAClB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;YACrD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAE9B,IAAI,KAAK,CAAC;IACV,IAAI,CAAC;QACH,KAAK,GAAG,eAAe,EAAE,CAAC;IAC5B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,gFAAgF;QAChF,MAAM,CAAC,KAAK,CACV,yCAAyC,eAAe,EAAE,yBACxD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,mBAAmB,CACpB,CAAC;QACF,iBAAiB,EAAE,CAAC;QACpB,MAAM,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QACzD,OAAO;IACT,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,kBAAkB,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3D,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,gEAAgE;QAChE,IAAI,GAAG,YAAY,eAAe,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YACnE,MAAM,CAAC,KAAK,CAAC,8DAA8D,GAAG,CAAC,OAAO,yCAAyC,CAAC,CAAC;QACnI,CAAC;aAAM,CAAC;YACN,sEAAsE;YACtE,qEAAqE;YACrE,MAAM,CAAC,KAAK,CACV,kDACE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,yCAAyC,CAC1C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,iBAAiB,EAAE,CAAC;IACpB,qBAAqB,EAAE,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bridge auth status` — prints whether a credentials file exists, who it's
|
|
3
|
+
* for, and how long until it expires.
|
|
4
|
+
*
|
|
5
|
+
* Output is plain text (one key=value per line after the first), tuned for
|
|
6
|
+
* humans. Other CLI commands emit structured JSON — auth status is the one
|
|
7
|
+
* place where a developer is most likely to be eyeballing the result, so we
|
|
8
|
+
* optimize for readability over machine-parseability.
|
|
9
|
+
*
|
|
10
|
+
* If the user wants JSON, they can run `cat ~/.config/bridge/credentials.json`.
|
|
11
|
+
*/
|
|
12
|
+
import type { Command } from 'commander';
|
|
13
|
+
export declare function registerAuthStatusCommand(auth: Command): void;
|
|
14
|
+
//# sourceMappingURL=status.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.command.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/status.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAc7D"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { credentialsPath, isExpired, readCredentials } from '../../credentials.js';
|
|
2
|
+
import { formatRelativeTime } from '../../auth/relative-time.js';
|
|
3
|
+
export function registerAuthStatusCommand(auth) {
|
|
4
|
+
auth
|
|
5
|
+
.command('status')
|
|
6
|
+
.description('Show current authentication state (who, which app, expiry)')
|
|
7
|
+
.action(() => {
|
|
8
|
+
try {
|
|
9
|
+
runStatus();
|
|
10
|
+
process.exitCode = 0;
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
14
|
+
process.stderr.write(`bridge auth status: ${msg}\n`);
|
|
15
|
+
process.exitCode = 1;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function runStatus() {
|
|
20
|
+
const stdout = process.stdout;
|
|
21
|
+
// Prefer the credentials file; report on `BRIDGE_API_KEY` separately if set
|
|
22
|
+
// (so a CI user setting the env var sees something useful).
|
|
23
|
+
const envApiKey = process.env.BRIDGE_API_KEY?.trim();
|
|
24
|
+
let creds;
|
|
25
|
+
try {
|
|
26
|
+
creds = readCredentials();
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
stdout.write(`Credentials file at ${credentialsPath()} is unreadable: ${err instanceof Error ? err.message : String(err)}\n` + 'Run `bridge auth login` to refresh, or delete the file manually.\n');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (!creds) {
|
|
33
|
+
if (envApiKey && envApiKey.length > 0) {
|
|
34
|
+
stdout.write('Using BRIDGE_API_KEY from environment (service-account / CI path).\n' +
|
|
35
|
+
'Run `bridge auth login` to switch to interactive credentials.\n');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
stdout.write('Not logged in. Run `bridge auth login`.\n');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const expiryDate = new Date(creds.expiresAt);
|
|
42
|
+
const expiryDelta = expiryDate.getTime() - Date.now();
|
|
43
|
+
const expiryRel = formatRelativeTime(expiryDelta);
|
|
44
|
+
const expiredLabel = isExpired(creds) ? ' (EXPIRED)' : '';
|
|
45
|
+
stdout.write(`Logged in as ${creds.user.email}\n`);
|
|
46
|
+
stdout.write(` app=${creds.app.name} (${creds.app.id})\n`);
|
|
47
|
+
stdout.write(` expires=${expiryRel} — ${creds.expiresAt}${expiredLabel}\n`);
|
|
48
|
+
stdout.write(` baseUrl=${creds.baseUrl}\n`);
|
|
49
|
+
if (creds.label)
|
|
50
|
+
stdout.write(` label=${creds.label}\n`);
|
|
51
|
+
stdout.write(` credentials=${credentialsPath()}\n`);
|
|
52
|
+
if (envApiKey && envApiKey.length > 0) {
|
|
53
|
+
stdout.write('\nNote: BRIDGE_API_KEY is also set in your environment — it takes precedence over the credentials file.\n');
|
|
54
|
+
}
|
|
55
|
+
if (isExpired(creds)) {
|
|
56
|
+
process.exitCode = 0; // status is informational; don't fail just because expired.
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=status.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.command.js","sourceRoot":"","sources":["../../../src/commands/auth/status.command.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* `bridge auth …` — top-level wiring for the auth command tree.
|
|
3
|
+
*
|
|
4
|
+
* Subcommand modules live in `./auth/*.command.ts`:
|
|
5
|
+
* - `login` (TBP-113): browser-based PKCE auth.
|
|
6
|
+
* - `logout` (TBP-113): revoke + delete credentials.
|
|
7
|
+
* - `status` (TBP-113): show current login state.
|
|
8
|
+
* - `config`/`mfa`/`password-policy`: pre-existing app auth-config commands.
|
|
9
|
+
*/
|
|
10
|
+
import type { Command } from 'commander';
|
|
2
11
|
export declare function registerAuthCommands(program: Command): void;
|
|
3
12
|
//# sourceMappingURL=auth.command.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.command.d.ts","sourceRoot":"","sources":["../../src/commands/auth.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.command.d.ts","sourceRoot":"","sources":["../../src/commands/auth.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAY3D"}
|
|
@@ -1,58 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { registerAuthLoginCommand } from './auth/login.command.js';
|
|
2
|
+
import { registerAuthLogoutCommand } from './auth/logout.command.js';
|
|
3
|
+
import { registerAuthStatusCommand } from './auth/status.command.js';
|
|
4
|
+
import { registerAuthConfigCommands } from './auth/config.command.js';
|
|
3
5
|
export function registerAuthCommands(program) {
|
|
4
|
-
const auth = program
|
|
5
|
-
|
|
6
|
-
.description('
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
magicLinkEnabled: app.magicLinkEnabled,
|
|
14
|
-
googleSsoEnabled: app.googleSsoEnabled,
|
|
15
|
-
azureAdSsoEnabled: app.azureAdSsoEnabled,
|
|
16
|
-
githubSsoEnabled: app.githubSsoEnabled,
|
|
17
|
-
linkedinSsoEnabled: app.linkedinSsoEnabled,
|
|
18
|
-
facebookSsoEnabled: app.facebookSsoEnabled,
|
|
19
|
-
appleSsoEnabled: app.appleSsoEnabled,
|
|
20
|
-
onboardingFlow: app.onboardingFlow,
|
|
21
|
-
tenantSelfSignup: app.tenantSelfSignup,
|
|
22
|
-
accessTokenTTL: app.accessTokenTTL,
|
|
23
|
-
refreshTokenTTL: app.refreshTokenTTL,
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
catch (err) {
|
|
27
|
-
outputError(err);
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
auth.command('mfa')
|
|
31
|
-
.description('Enable or disable MFA')
|
|
32
|
-
.requiredOption('--enabled <bool>', 'true or false', (v) => v === 'true')
|
|
33
|
-
.action(async (opts) => {
|
|
34
|
-
try {
|
|
35
|
-
outputSuccess(await getManagementClient().app.update({ mfaEnabled: opts.enabled }));
|
|
36
|
-
}
|
|
37
|
-
catch (err) {
|
|
38
|
-
outputError(err);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
auth.command('password-policy')
|
|
42
|
-
.description('Update access token TTL')
|
|
43
|
-
.option('--access-token-ttl <seconds>', 'Access token TTL in seconds', parseInt)
|
|
44
|
-
.option('--refresh-token-ttl <seconds>', 'Refresh token TTL in seconds', parseInt)
|
|
45
|
-
.action(async (opts) => {
|
|
46
|
-
try {
|
|
47
|
-
const data = Object.fromEntries(Object.entries({
|
|
48
|
-
accessTokenTTL: opts.accessTokenTtl,
|
|
49
|
-
refreshTokenTTL: opts.refreshTokenTtl,
|
|
50
|
-
}).filter(([, v]) => v !== undefined));
|
|
51
|
-
outputSuccess(await getManagementClient().app.update(data));
|
|
52
|
-
}
|
|
53
|
-
catch (err) {
|
|
54
|
-
outputError(err);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
6
|
+
const auth = program
|
|
7
|
+
.command('auth')
|
|
8
|
+
.description('Authenticate with Bridge and manage app auth configuration');
|
|
9
|
+
// TBP-113 — interactive credentials.
|
|
10
|
+
registerAuthLoginCommand(auth);
|
|
11
|
+
registerAuthLogoutCommand(auth);
|
|
12
|
+
registerAuthStatusCommand(auth);
|
|
13
|
+
// Pre-existing — app-level auth configuration.
|
|
14
|
+
registerAuthConfigCommands(auth);
|
|
57
15
|
}
|
|
58
16
|
//# sourceMappingURL=auth.command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.command.js","sourceRoot":"","sources":["../../src/commands/auth.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.command.js","sourceRoot":"","sources":["../../src/commands/auth.command.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAEtE,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,MAAM,IAAI,GAAG,OAAO;SACjB,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,4DAA4D,CAAC,CAAC;IAE7E,qCAAqC;IACrC,wBAAwB,CAAC,IAAI,CAAC,CAAC;IAC/B,yBAAyB,CAAC,IAAI,CAAC,CAAC;IAChC,yBAAyB,CAAC,IAAI,CAAC,CAAC;IAEhC,+CAA+C;IAC/C,0BAA0B,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { outputSuccess, outputError } from '../output.js';
|
|
4
|
-
const GUIDE_BASE_URL = 'https://raw.githubusercontent.com/
|
|
4
|
+
const GUIDE_BASE_URL = 'https://raw.githubusercontent.com/thebridgedev';
|
|
5
5
|
const GUIDE_REPOS = {
|
|
6
6
|
react: 'bridge-react/main',
|
|
7
7
|
svelte: 'bridge-svelte/main',
|
|
@@ -94,7 +94,7 @@ async function fetchGuide(tech, feature) {
|
|
|
94
94
|
guideCache.set(cacheKey, { content, fetchedAt: Date.now() });
|
|
95
95
|
return content;
|
|
96
96
|
}
|
|
97
|
-
const MASTER_PROMPT_GITHUB_URL = 'https://raw.githubusercontent.com/
|
|
97
|
+
const MASTER_PROMPT_GITHUB_URL = 'https://raw.githubusercontent.com/thebridgedev/bridge-cli/main/bridge-cli/prompts/master-integration-prompt.md';
|
|
98
98
|
async function fetchMasterPrompt() {
|
|
99
99
|
// Local override for development
|
|
100
100
|
const localDir = process.env.BRIDGE_GUIDE_LOCAL_DIR;
|
|
@@ -121,7 +121,7 @@ This guide covers integrating Bridge into any language/framework using the REST
|
|
|
121
121
|
Bridge issues JWTs signed with PS256. Verify them using your app's JWKS endpoint:
|
|
122
122
|
|
|
123
123
|
\`\`\`
|
|
124
|
-
GET https://
|
|
124
|
+
GET https://api.thebridge.dev/v1/account/app/.well-known/jwks.json
|
|
125
125
|
\`\`\`
|
|
126
126
|
|
|
127
127
|
Use a JWT library in your language that supports JWKS auto-refresh:
|
|
@@ -144,7 +144,7 @@ The access token contains:
|
|
|
144
144
|
|
|
145
145
|
Evaluate flags server-side:
|
|
146
146
|
\`\`\`
|
|
147
|
-
POST https://
|
|
147
|
+
POST https://api.thebridge.dev/cloud-views/flags/bulkEvaluate/{appId}
|
|
148
148
|
Authorization: Bearer <user-access-token>
|
|
149
149
|
\`\`\`
|
|
150
150
|
|
|
@@ -152,7 +152,7 @@ Authorization: Bearer <user-access-token>
|
|
|
152
152
|
|
|
153
153
|
Use the Bridge REST API with an API token:
|
|
154
154
|
\`\`\`
|
|
155
|
-
GET https://
|
|
155
|
+
GET https://api.thebridge.dev/v1/account/tenant
|
|
156
156
|
x-api-key: <your-api-token>
|
|
157
157
|
\`\`\`
|
|
158
158
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guide.command.js","sourceRoot":"","sources":["../../src/commands/guide.command.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"guide.command.js","sourceRoot":"","sources":["../../src/commands/guide.command.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
import { BridgeManagement } from '@nebulr-group/bridge-auth-core';
|
|
2
|
+
export declare const DEFAULT_BASE_URL = "https://api.thebridge.dev";
|
|
3
|
+
/**
|
|
4
|
+
* Resolution order:
|
|
5
|
+
* 1. `~/.config/bridge/credentials.json` (or `$XDG_CONFIG_HOME/bridge/credentials.json`)
|
|
6
|
+
* written by `bridge auth login`. The interactive primary path. Token
|
|
7
|
+
* carries the appId baked in by /v1/auth/cli/token, so post-login the
|
|
8
|
+
* JWT is the source of truth for which app the CLI operates on.
|
|
9
|
+
* 2. `BRIDGE_API_KEY` env var (CI / service-account fallback). Used when no
|
|
10
|
+
* credentials file exists — typical CI runner shape.
|
|
11
|
+
* 3. Throw `ConfigError("Not logged in. Run `bridge auth login`.")`.
|
|
12
|
+
*
|
|
13
|
+
* Note: credentials-file wins over env so `bridge auth login` does what users
|
|
14
|
+
* expect — the new login takes effect immediately. CI is unaffected because
|
|
15
|
+
* runners typically have no credentials file and fall through to step 2.
|
|
16
|
+
*
|
|
17
|
+
* If a credentials file exists but its `expiresAt` is in the past, we fall
|
|
18
|
+
* through to env (if set) — same as if there were no file. Otherwise throw a
|
|
19
|
+
* friendly error pointing the user back to `bridge auth login`.
|
|
20
|
+
*/
|
|
2
21
|
export declare function getManagementClient(): BridgeManagement;
|
|
22
|
+
/**
|
|
23
|
+
* For tests and for `bridge auth logout` / `bridge auth status` — they need
|
|
24
|
+
* to reset the cached client between operations.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resetManagementClient(): void;
|
|
3
27
|
export declare function resolveTenantId(opts: {
|
|
4
28
|
tenantId?: string;
|
|
5
29
|
}): string;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAGlE,eAAO,MAAM,gBAAgB,8BAA8B,CAAC;AAI5D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,IAAI,gBAAgB,CA+CtD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAQnE;AAED,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B"}
|
package/dist/config.js
CHANGED
|
@@ -1,19 +1,75 @@
|
|
|
1
1
|
import { BridgeManagement } from '@nebulr-group/bridge-auth-core';
|
|
2
|
+
import { isExpired, readCredentials } from './credentials.js';
|
|
3
|
+
export const DEFAULT_BASE_URL = 'https://api.thebridge.dev';
|
|
2
4
|
let _client = null;
|
|
5
|
+
/**
|
|
6
|
+
* Resolution order:
|
|
7
|
+
* 1. `~/.config/bridge/credentials.json` (or `$XDG_CONFIG_HOME/bridge/credentials.json`)
|
|
8
|
+
* written by `bridge auth login`. The interactive primary path. Token
|
|
9
|
+
* carries the appId baked in by /v1/auth/cli/token, so post-login the
|
|
10
|
+
* JWT is the source of truth for which app the CLI operates on.
|
|
11
|
+
* 2. `BRIDGE_API_KEY` env var (CI / service-account fallback). Used when no
|
|
12
|
+
* credentials file exists — typical CI runner shape.
|
|
13
|
+
* 3. Throw `ConfigError("Not logged in. Run `bridge auth login`.")`.
|
|
14
|
+
*
|
|
15
|
+
* Note: credentials-file wins over env so `bridge auth login` does what users
|
|
16
|
+
* expect — the new login takes effect immediately. CI is unaffected because
|
|
17
|
+
* runners typically have no credentials file and fall through to step 2.
|
|
18
|
+
*
|
|
19
|
+
* If a credentials file exists but its `expiresAt` is in the past, we fall
|
|
20
|
+
* through to env (if set) — same as if there were no file. Otherwise throw a
|
|
21
|
+
* friendly error pointing the user back to `bridge auth login`.
|
|
22
|
+
*/
|
|
3
23
|
export function getManagementClient() {
|
|
4
24
|
if (_client)
|
|
5
25
|
return _client;
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
26
|
+
const debug = process.env.BRIDGE_DEBUG === 'true';
|
|
27
|
+
const envApiKey = process.env.BRIDGE_API_KEY?.trim();
|
|
28
|
+
const envBaseUrl = process.env.BRIDGE_BASE_URL?.trim();
|
|
29
|
+
let apiKey;
|
|
30
|
+
let baseUrl;
|
|
31
|
+
let source;
|
|
32
|
+
// 1. Credentials file from `bridge auth login` (interactive primary).
|
|
33
|
+
const creds = safeReadCredentials();
|
|
34
|
+
if (creds && !isExpired(creds)) {
|
|
35
|
+
apiKey = creds.apiKey;
|
|
36
|
+
// Env override still wins for baseUrl (useful for hitting a local bridge-api
|
|
37
|
+
// with a token issued by prod, or vice versa during dev).
|
|
38
|
+
baseUrl = envBaseUrl && envBaseUrl.length > 0 ? envBaseUrl : creds.baseUrl;
|
|
39
|
+
source = 'credentials-file';
|
|
40
|
+
}
|
|
41
|
+
else if (envApiKey && envApiKey.length > 0) {
|
|
42
|
+
// 2. BRIDGE_API_KEY env var (CI / service-account fallback).
|
|
43
|
+
apiKey = envApiKey;
|
|
44
|
+
baseUrl = envBaseUrl && envBaseUrl.length > 0 ? envBaseUrl : DEFAULT_BASE_URL;
|
|
45
|
+
source = 'env';
|
|
46
|
+
}
|
|
47
|
+
else if (creds && isExpired(creds)) {
|
|
48
|
+
// 3a. Found a credentials file but token expired; no env fallback either.
|
|
49
|
+
throw new ConfigError('Token expired. Run `bridge auth login` to re-authenticate.');
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// 3b. No credentials at all.
|
|
53
|
+
throw new ConfigError('Not logged in. Run `bridge auth login`.');
|
|
54
|
+
}
|
|
55
|
+
if (debug) {
|
|
56
|
+
const baseSource = envBaseUrl && envBaseUrl.length > 0
|
|
57
|
+
? 'env'
|
|
58
|
+
: source === 'env'
|
|
59
|
+
? 'default'
|
|
60
|
+
: 'credentials-file';
|
|
61
|
+
console.error(`[bridge-cli] apiKey=<redacted from ${source}> baseUrl=${baseUrl} (${baseSource})`);
|
|
62
|
+
}
|
|
63
|
+
_client = new BridgeManagement({ apiKey, baseUrl, debug });
|
|
15
64
|
return _client;
|
|
16
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* For tests and for `bridge auth logout` / `bridge auth status` — they need
|
|
68
|
+
* to reset the cached client between operations.
|
|
69
|
+
*/
|
|
70
|
+
export function resetManagementClient() {
|
|
71
|
+
_client = null;
|
|
72
|
+
}
|
|
17
73
|
export function resolveTenantId(opts) {
|
|
18
74
|
const tenantId = opts.tenantId || process.env.BRIDGE_TENANT_ID;
|
|
19
75
|
if (!tenantId) {
|
|
@@ -27,4 +83,18 @@ export class ConfigError extends Error {
|
|
|
27
83
|
this.name = 'ConfigError';
|
|
28
84
|
}
|
|
29
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Wraps `readCredentials()` so a malformed file produces a `ConfigError` (caught
|
|
88
|
+
* by `outputError`) rather than a raw `Error` stack trace. Returns `null` if
|
|
89
|
+
* the file just doesn't exist (caller decides what to do).
|
|
90
|
+
*/
|
|
91
|
+
function safeReadCredentials() {
|
|
92
|
+
try {
|
|
93
|
+
return readCredentials();
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
throw new ConfigError(`Could not read credentials file: ${err instanceof Error ? err.message : String(err)}\n` +
|
|
97
|
+
'Run `bridge auth login` to refresh, or delete the file manually.');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
30
100
|
//# sourceMappingURL=config.js.map
|