switch-profile 2.0.1 → 2.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/README.md +21 -7
- package/dist/cli.js +145 -34
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -11,21 +11,23 @@ npx switch-profile
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
```
|
|
14
|
-
┌ switch-profile 2.
|
|
14
|
+
┌ switch-profile 2.1.0
|
|
15
15
|
│
|
|
16
16
|
│ ● acme-prod · Admin · 111111111111 · ap-southeast-2 · PROD · SSO ✓ auto-refresh · logged in 3h ago
|
|
17
17
|
│
|
|
18
18
|
◆ Switch to · type a name, account, role or client
|
|
19
|
-
│ Search: dev
|
|
20
|
-
│ ● acme-dev Admin 222222222222 ap-southeast-2
|
|
19
|
+
│ Search: dev█ (3 matches)
|
|
20
|
+
│ ● acme-dev Admin 222222222222 ap-southeast-2 used 2d ago
|
|
21
21
|
│ ○ globex-dev ReadOnly 333333333333 us-east-1
|
|
22
22
|
│ ○ initech-dev Admin 444444444444 eu-west-1
|
|
23
|
-
|
|
23
|
+
│
|
|
24
|
+
│ [Log in] [Add] [Remove] [Log out] [Settings]
|
|
25
|
+
└ ↑↓ choose · enter switch · tab actions · esc quit
|
|
24
26
|
```
|
|
25
27
|
|
|
26
28
|
## Why it's great
|
|
27
29
|
|
|
28
|
-
- **Seconds, not minutes.** Fuzzy search across profile name, account ID, account name, role, client and region, with your most-used accounts first. `sp acme prod` switches without even opening the
|
|
30
|
+
- **Seconds, not minutes.** Fuzzy search across profile name, account ID, account name, role, client and region, with your most-used accounts first, and every other action one Tab away. `sp acme prod` switches without even opening the home screen.
|
|
29
31
|
- **Logged in when you need it.** If a session has expired, it logs you in on the spot, then never again until the session ends: credentials refresh on their own in the AWS CLI, SDKs and Terraform.
|
|
30
32
|
- **Every terminal on its own account.** With the `sp` shortcut, each terminal keeps its own `AWS_PROFILE`, plus tab-completion of your profile names.
|
|
31
33
|
- **Made for remote machines.** On a server reached over SSH, the login code lands in your laptop's clipboard, or scan a QR code with your phone.
|
|
@@ -51,6 +53,7 @@ npx switch-profile
|
|
|
51
53
|
- [Why it's great](#why-its-great)
|
|
52
54
|
- [Built on AWS best practices](#built-on-aws-best-practices)
|
|
53
55
|
- [Quick start](#quick-start)
|
|
56
|
+
- [The home screen](#the-home-screen)
|
|
54
57
|
- [Commands](#commands)
|
|
55
58
|
- [Working on remote machines (SSH)](#working-on-remote-machines-ssh)
|
|
56
59
|
- [Importing a client's accounts](#importing-a-clients-accounts)
|
|
@@ -90,11 +93,20 @@ sp acme prod # fuzzy match: switches if exactly one profile matches
|
|
|
90
93
|
|
|
91
94
|
No profiles yet? `switch-profile` starts the **Add profiles** flow. To import every account of your company's or client's SSO portal, see [Importing a client's accounts](#importing-a-clients-accounts).
|
|
92
95
|
|
|
96
|
+
## The home screen
|
|
97
|
+
|
|
98
|
+
Running `sp` (or `npx switch-profile`) with no arguments opens the home screen:
|
|
99
|
+
|
|
100
|
+
- **Type and press Enter** to switch. That's the whole path for everyday use.
|
|
101
|
+
- **Tab** moves to the action bar below the list, which is always visible however many profiles you have: **Log in**, **Add**, **Remove**, **Log out**, **Settings**. Use ←→ to choose and Enter to open.
|
|
102
|
+
- **Every action opens as a page and comes back** to the home screen when it's done. **Esc** goes back from a page, and quits from the home screen.
|
|
103
|
+
- A switch ends the session, which is what lets `sp` set `AWS_PROFILE` in your terminal.
|
|
104
|
+
|
|
93
105
|
## Commands
|
|
94
106
|
|
|
95
107
|
| Command | What it does |
|
|
96
108
|
|---------|--------------|
|
|
97
|
-
| `switch-profile [profile...]` | Opens the
|
|
109
|
+
| `switch-profile [profile...]` | Opens the home screen (search and switch, plus the action bar). With words: an exact name or a unique fuzzy match switches directly; otherwise the home screen opens pre-filtered (or exits 3 when non-interactive). |
|
|
98
110
|
| `use <profile>` | Switches to a profile by its exact name (no fuzzy matching). |
|
|
99
111
|
| `status [--json]` | Shows the default profile, its login state, and what this terminal uses. |
|
|
100
112
|
| `login [profile] [--device\|--browser]` | Starts a fresh login now, even if the session is still valid. Defaults to this terminal's `AWS_PROFILE`, then the default profile. |
|
|
@@ -176,6 +188,8 @@ AWS_PROFILE=acme-dev terraform plan
|
|
|
176
188
|
|
|
177
189
|
## Settings
|
|
178
190
|
|
|
191
|
+
Open **Settings** from the home screen's action bar (Tab, then → to Settings), or run it directly:
|
|
192
|
+
|
|
179
193
|
```shell
|
|
180
194
|
sp settings
|
|
181
195
|
```
|
|
@@ -243,7 +257,7 @@ The completion registers only if `compinit` ran before the `switch-profile` bloc
|
|
|
243
257
|
|
|
244
258
|
### Commands still use the wrong account
|
|
245
259
|
|
|
246
|
-
`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY` in the environment override every profile, and `AWS_REGION` overrides the profile's region. The
|
|
260
|
+
`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY` in the environment override every profile, and `AWS_REGION` overrides the profile's region. The home screen warns about them; switching with `sp` clears the credential variables (not the region).
|
|
247
261
|
|
|
248
262
|
### AWS CLI not found
|
|
249
263
|
|
package/dist/cli.js
CHANGED
|
@@ -2836,6 +2836,30 @@ var require_src = __commonJS({
|
|
|
2836
2836
|
});
|
|
2837
2837
|
|
|
2838
2838
|
// node_modules/@clack/core/dist/index.mjs
|
|
2839
|
+
var dist_exports = {};
|
|
2840
|
+
__export(dist_exports, {
|
|
2841
|
+
AutocompletePrompt: () => T$1,
|
|
2842
|
+
CANCEL_SYMBOL: () => CANCEL_SYMBOL,
|
|
2843
|
+
ConfirmPrompt: () => r,
|
|
2844
|
+
DatePrompt: () => U,
|
|
2845
|
+
GroupMultiSelectPrompt: () => u$2,
|
|
2846
|
+
MultiLinePrompt: () => h,
|
|
2847
|
+
MultiSelectPrompt: () => a,
|
|
2848
|
+
PasswordPrompt: () => u$1,
|
|
2849
|
+
Prompt: () => y,
|
|
2850
|
+
SelectKeyPrompt: () => u3,
|
|
2851
|
+
SelectPrompt: () => n$1,
|
|
2852
|
+
TextPrompt: () => n2,
|
|
2853
|
+
block: () => block,
|
|
2854
|
+
getColumns: () => getColumns,
|
|
2855
|
+
getRows: () => getRows,
|
|
2856
|
+
isAccessible: () => isAccessible,
|
|
2857
|
+
isCancel: () => isCancel,
|
|
2858
|
+
runValidation: () => runValidation,
|
|
2859
|
+
settings: () => settings,
|
|
2860
|
+
updateSettings: () => updateSettings,
|
|
2861
|
+
wrapTextWithPrefix: () => wrapTextWithPrefix
|
|
2862
|
+
});
|
|
2839
2863
|
function findCursor(s, o2, l2) {
|
|
2840
2864
|
if (!l2.some((r2) => !r2.disabled))
|
|
2841
2865
|
return s;
|
|
@@ -3805,8 +3829,8 @@ ${i2}` : `${s}${(0, import_node_util.styleText)("inverse", r2)}${i2}`;
|
|
|
3805
3829
|
});
|
|
3806
3830
|
|
|
3807
3831
|
// node_modules/@clack/prompts/dist/index.mjs
|
|
3808
|
-
var
|
|
3809
|
-
__export(
|
|
3832
|
+
var dist_exports2 = {};
|
|
3833
|
+
__export(dist_exports2, {
|
|
3810
3834
|
CANCEL_SYMBOL: () => CANCEL_SYMBOL,
|
|
3811
3835
|
MULTISELECT_INSTRUCTIONS: () => MULTISELECT_INSTRUCTIONS,
|
|
3812
3836
|
SELECT_INSTRUCTIONS: () => SELECT_INSTRUCTIONS,
|
|
@@ -5261,7 +5285,7 @@ var require_ui = __commonJS({
|
|
|
5261
5285
|
let h2 = Math.floor(m3 / 60);
|
|
5262
5286
|
return h2 < 48 ? `${h2}h ago` : `${Math.floor(h2 / 24)}d ago`;
|
|
5263
5287
|
}, spinner2 = (options) => {
|
|
5264
|
-
let p4 = (init_dist4(), __toCommonJS(
|
|
5288
|
+
let p4 = (init_dist4(), __toCommonJS(dist_exports2));
|
|
5265
5289
|
if (process.stdout.isTTY && !env.ACCESSIBLE)
|
|
5266
5290
|
return p4.spinner(options);
|
|
5267
5291
|
let accessible = process.stdout.isTTY;
|
|
@@ -5277,7 +5301,7 @@ var require_ui = __commonJS({
|
|
|
5277
5301
|
isCancelled: !1
|
|
5278
5302
|
};
|
|
5279
5303
|
}, timerSpinner = () => {
|
|
5280
|
-
let p4 = (init_dist4(), __toCommonJS(
|
|
5304
|
+
let p4 = (init_dist4(), __toCommonJS(dist_exports2));
|
|
5281
5305
|
if (!process.stdout.isTTY || env.ACCESSIBLE)
|
|
5282
5306
|
return spinner2();
|
|
5283
5307
|
let frames = unicode2 ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["-", "\\", "|", "/"], timer = null, message = "", started = 0, i2 = 0, clear = () => process.stdout.write("\r\x1B[2K"), render = () => {
|
|
@@ -5327,7 +5351,7 @@ var require_package = __commonJS({
|
|
|
5327
5351
|
"package.json"(exports2, module2) {
|
|
5328
5352
|
module2.exports = {
|
|
5329
5353
|
name: "switch-profile",
|
|
5330
|
-
version: "2.0
|
|
5354
|
+
version: "2.1.0",
|
|
5331
5355
|
main: "index.js",
|
|
5332
5356
|
bin: {
|
|
5333
5357
|
"switch-profile": "index.js"
|
|
@@ -5363,6 +5387,7 @@ var require_package = __commonJS({
|
|
|
5363
5387
|
author: "Nicolas Dao",
|
|
5364
5388
|
license: "BSD-3-Clause",
|
|
5365
5389
|
devDependencies: {
|
|
5390
|
+
"@clack/core": "^1.5.1",
|
|
5366
5391
|
"@clack/prompts": "^1.8.1",
|
|
5367
5392
|
"@eslint/js": "^10.0.1",
|
|
5368
5393
|
chai: "^4.1.2",
|
|
@@ -6288,7 +6313,7 @@ var require_migrate = __commonJS({
|
|
|
6288
6313
|
// src/commands/common.js
|
|
6289
6314
|
var require_common = __commonJS({
|
|
6290
6315
|
"src/commands/common.js"(exports2, module2) {
|
|
6291
|
-
var p4 = (init_dist4(), __toCommonJS(
|
|
6316
|
+
var p4 = (init_dist4(), __toCommonJS(dist_exports2)), aws = require_aws(), settings2 = require_settings(), shell = require_shell(), migrate = require_migrate(), ui2 = require_ui(), CancelError2 = class extends Error {
|
|
6292
6317
|
}, ask = async (promise) => {
|
|
6293
6318
|
let value = await promise;
|
|
6294
6319
|
if (p4.isCancel(value))
|
|
@@ -7364,7 +7389,7 @@ var require_clipboard = __commonJS({
|
|
|
7364
7389
|
// src/commands/login-flow.js
|
|
7365
7390
|
var require_login_flow = __commonJS({
|
|
7366
7391
|
"src/commands/login-flow.js"(exports2, module2) {
|
|
7367
|
-
var { spawn } = require("child_process"), p4 = (init_dist4(), __toCommonJS(
|
|
7392
|
+
var { spawn } = require("child_process"), p4 = (init_dist4(), __toCommonJS(dist_exports2)), { renderUnicodeCompact } = require_dist(), aws = require_aws(), settings2 = require_settings(), { parseLoginOutput, isRemoteSession, atLeast } = require_login(), clipboard = require_clipboard(), ui2 = require_ui(), { CancelError: CancelError2 } = require_common(), IS_WINDOWS = process.platform == "win32", RAW_OUTPUT_AFTER_MS = 1e4, clipboardNote = (result) => result == "local" ? ui2.ok("\u{1F4CB} copied") : result == "terminal" ? ui2.dim("\u{1F4CB} sent to your clipboard") : "", ssoLogin = async (target, { label, loginKey, interactive, loginMode }) => {
|
|
7368
7393
|
let current = await settings2.read(), args = await aws.ssoLoginArgs(target, loginMode || settings2.getLoginMode(current)), legacyCli = !atLeast(await aws.getAwsCliVersion(), [2, 22, 0]), device = args.includes("--use-device-code") || legacyCli, remote = isRemoteSession(process.env, process.platform);
|
|
7369
7394
|
if (!interactive)
|
|
7370
7395
|
return plainLogin(args, label);
|
|
@@ -7445,10 +7470,74 @@ ${detail}` : ""}`, {
|
|
|
7445
7470
|
}
|
|
7446
7471
|
});
|
|
7447
7472
|
|
|
7473
|
+
// src/home.js
|
|
7474
|
+
var require_home = __commonJS({
|
|
7475
|
+
"src/home.js"(exports2, module2) {
|
|
7476
|
+
var { AutocompletePrompt } = (init_dist3(), __toCommonJS(dist_exports)), { S_BAR: S_BAR2, S_BAR_END: S_BAR_END2, S_RADIO_ACTIVE: S_RADIO_ACTIVE2, S_RADIO_INACTIVE: S_RADIO_INACTIVE2, symbol: symbol2, limitOptions: limitOptions2 } = (init_dist4(), __toCommonJS(dist_exports2)), ui2 = require_ui(), ACTION_PREFIX = "__action__:", nextFocus = (state, { name, char }) => {
|
|
7477
|
+
let { area, index, count, hasRows } = state;
|
|
7478
|
+
return name == "tab" ? { ...state, area: area == "list" || !hasRows ? "actions" : "list" } : area != "actions" ? state : name == "left" ? { ...state, index: (index - 1 + count) % count } : name == "right" ? { ...state, index: (index + 1) % count } : name == "return" ? { ...state, submit: !0 } : (name == "up" || name == "down") && hasRows ? { ...state, area: "list" } : char && char.length == 1 && char >= " " && hasRows ? { ...state, area: "list" } : state;
|
|
7479
|
+
}, HomePrompt = class extends AutocompletePrompt {
|
|
7480
|
+
constructor(opts) {
|
|
7481
|
+
super(opts), this.actions = opts.actions, this.area = this.options.length ? "list" : "actions", this.actionIndex = 0, this.on("key", (char, key) => {
|
|
7482
|
+
let next = nextFocus(
|
|
7483
|
+
{ area: this.area, index: this.actionIndex, count: this.actions.length, hasRows: this.filteredOptions.length > 0 },
|
|
7484
|
+
{ name: key && key.name, char }
|
|
7485
|
+
);
|
|
7486
|
+
this.area = next.area, this.actionIndex = next.index, next.submit && (this.value = ACTION_PREFIX + this.actions[this.actionIndex].key);
|
|
7487
|
+
});
|
|
7488
|
+
}
|
|
7489
|
+
}, actionBar = (actions, focused) => actions.map((a2, i2) => {
|
|
7490
|
+
let label = ` ${a2.label} `;
|
|
7491
|
+
return i2 === focused ? ui2.style(["inverse", "cyan"], label) : ui2.dim(`[${label.trim()}]`);
|
|
7492
|
+
}).join(" "), home = ({ message, rows, actions, initialQuery, maxItems, input, output }) => new HomePrompt({
|
|
7493
|
+
actions,
|
|
7494
|
+
input,
|
|
7495
|
+
output,
|
|
7496
|
+
initialUserInput: initialQuery || void 0,
|
|
7497
|
+
options() {
|
|
7498
|
+
return rows(this.userInput || "");
|
|
7499
|
+
},
|
|
7500
|
+
validate: (value) => value === void 0 ? "Nothing matches: change the search, or press Tab for actions." : void 0,
|
|
7501
|
+
render() {
|
|
7502
|
+
let gray = (s) => ui2.style("gray", s), title = `${gray(S_BAR2)}
|
|
7503
|
+
${symbol2(this.state)} ${message}`;
|
|
7504
|
+
if (this.state == "submit") {
|
|
7505
|
+
let v = String(this.value || "");
|
|
7506
|
+
if (v.startsWith(ACTION_PREFIX)) {
|
|
7507
|
+
let label = (actions.find((a2) => ACTION_PREFIX + a2.key == v) || {}).label || "";
|
|
7508
|
+
return `${gray(S_BAR2)}
|
|
7509
|
+
${symbol2(this.state)} ${ui2.dim("switch-profile \u203A")} ${ui2.strong(label)}`;
|
|
7510
|
+
}
|
|
7511
|
+
return `${title}
|
|
7512
|
+
${gray(S_BAR2)} ${ui2.dim(v)}`;
|
|
7513
|
+
}
|
|
7514
|
+
if (this.state == "cancel")
|
|
7515
|
+
return `${title}
|
|
7516
|
+
${gray(S_BAR2)}`;
|
|
7517
|
+
let bar = ui2.style(this.state == "error" ? "yellow" : "cyan", S_BAR2), end = ui2.style(this.state == "error" ? "yellow" : "cyan", S_BAR_END2), onList = this.area == "list", count = this.filteredOptions.length, lines = [title];
|
|
7518
|
+
return lines.push(`${bar} ${ui2.dim("Search:")} ${this.userInputWithCursor}${this.userInput ? ui2.dim(` (${count} match${count == 1 ? "" : "es"})`) : ""}`), count ? limitOptions2({
|
|
7519
|
+
cursor: this.cursor,
|
|
7520
|
+
options: this.filteredOptions,
|
|
7521
|
+
maxItems,
|
|
7522
|
+
output: this.output,
|
|
7523
|
+
rowPadding: 8,
|
|
7524
|
+
style: (option, active) => active && onList ? `${ui2.style("green", S_RADIO_ACTIVE2)} ${option.label}${option.hint ? ui2.dim(` ${option.hint}`) : ""}` : `${ui2.dim(S_RADIO_INACTIVE2)} ${ui2.dim(option.label)}`
|
|
7525
|
+
}).forEach((line) => lines.push(`${bar} ${line}`)) : lines.push(`${bar} ${ui2.warn(this.options.length ? "No matches" : "No profiles yet: Tab to Add")}`), lines.push(bar), lines.push(`${bar} ${actionBar(actions, onList ? -1 : this.actionIndex)}`), this.state == "error" && lines.push(`${bar} ${ui2.warn(this.error)}`), lines.push(`${end} ${ui2.dim(onList ? "\u2191\u2193 choose \xB7 enter switch \xB7 tab actions \xB7 esc quit" : "\u2190\u2192 choose \xB7 enter open \xB7 tab back to the list \xB7 esc quit")}`), lines.join(`
|
|
7526
|
+
`);
|
|
7527
|
+
}
|
|
7528
|
+
}).prompt();
|
|
7529
|
+
module2.exports = {
|
|
7530
|
+
ACTION_PREFIX,
|
|
7531
|
+
nextFocus,
|
|
7532
|
+
home
|
|
7533
|
+
};
|
|
7534
|
+
}
|
|
7535
|
+
});
|
|
7536
|
+
|
|
7448
7537
|
// src/commands/switch.js
|
|
7449
7538
|
var require_switch = __commonJS({
|
|
7450
7539
|
"src/commands/switch.js"(exports2, module2) {
|
|
7451
|
-
var p4 = (init_dist4(), __toCommonJS(
|
|
7540
|
+
var p4 = (init_dist4(), __toCommonJS(dist_exports2)), aws = require_aws(), settings2 = require_settings(), shell = require_shell(), rank = require_rank(), ui2 = require_ui(), { ask, preflight, loadState, loginKey, describe, loginState, CancelError: CancelError2 } = require_common(), { ssoLogin } = require_login_flow(), { home, ACTION_PREFIX } = require_home(), header = async (state, { warnings } = {}) => {
|
|
7452
7541
|
p4.intro(`${ui2.badge("switch-profile")} ${ui2.dim(settings2.CLI_VERSION)}`);
|
|
7453
7542
|
let lines = [];
|
|
7454
7543
|
if (state.defaultProfile) {
|
|
@@ -7463,7 +7552,7 @@ var require_switch = __commonJS({
|
|
|
7463
7552
|
lines.push(ui2.dim("No default profile yet. Pick one below."));
|
|
7464
7553
|
let terminal = process.env.AWS_PROFILE;
|
|
7465
7554
|
terminal && terminal != state.defaultName && lines.push(`${ui2.dim("This terminal uses")} ${ui2.accent(terminal)} ${ui2.dim("(AWS_PROFILE)")}`), p4.log.message(lines.join(`
|
|
7466
|
-
`)), warnEnv();
|
|
7555
|
+
`)), warnings && warnEnv();
|
|
7467
7556
|
}, warnEnv = () => {
|
|
7468
7557
|
let set = shell.CLEARED_VARS.filter((v) => process.env[v]);
|
|
7469
7558
|
if (!set.length)
|
|
@@ -7472,11 +7561,11 @@ var require_switch = __commonJS({
|
|
|
7472
7561
|
p4.log.warn(`${set.join(", ")} ${set.length > 1 ? "are" : "is"} set in this terminal and override${set.length > 1 ? "" : "s"} profiles.
|
|
7473
7562
|
${ui2.dim(viaShortcut ? "Switching clears them from this terminal." : `Unset ${set.length > 1 ? "them" : "it"}, or switch with ${shell.FUNCTION_NAME} to clear ${set.length > 1 ? "them" : "it"} automatically.`)}`);
|
|
7474
7563
|
}, ACTIONS = [
|
|
7475
|
-
{ key: "
|
|
7476
|
-
{ key: "
|
|
7477
|
-
{ key: "remove",
|
|
7478
|
-
{ key: "logout",
|
|
7479
|
-
{ key: "settings",
|
|
7564
|
+
{ key: "login", label: "Log in" },
|
|
7565
|
+
{ key: "add", label: "Add" },
|
|
7566
|
+
{ key: "remove", label: "Remove" },
|
|
7567
|
+
{ key: "logout", label: "Log out" },
|
|
7568
|
+
{ key: "settings", label: "Settings" }
|
|
7480
7569
|
], buildRows = (profiles, state) => {
|
|
7481
7570
|
let cols = ui2.columns(), showRole = cols >= 80, showRegion = cols >= 100, roleOf = (x2) => x2.sso_role_name || (x2.kind == "keys" ? "access keys" : x2.kind == "login" ? "console sign-in" : x2.kind), all = state.profiles, nameWidth = Math.min(Math.max(...all.map((x2) => x2.name.length), 8), 32), roleWidth = Math.min(Math.max(0, ...all.map((x2) => roleOf(x2).length)), 22), usage = state.settings.usage || {};
|
|
7482
7571
|
return profiles.map((x2) => {
|
|
@@ -7489,20 +7578,13 @@ ${ui2.dim(viaShortcut ? "Switching clears them from this terminal." : `Unset ${s
|
|
|
7489
7578
|
].filter((v) => v !== null).join(" ").trimEnd(), hint = x2.name == state.defaultName ? "current default" : [x2.accountName, usage[x2.name] ? `used ${ui2.ago(usage[x2.name].last)}` : null].filter(Boolean).join(" \xB7 ");
|
|
7490
7579
|
return { value: x2.name, label, hint: hint || void 0 };
|
|
7491
7580
|
});
|
|
7492
|
-
}, pick =
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
filter: () => !0,
|
|
7500
|
-
options() {
|
|
7501
|
-
let query = this.userInput || "", ranked = rank.rankProfiles(state.profiles, { query, usage: state.settings.usage, current: state.defaultName }), q = query.trim().toLowerCase(), matchingActions = actions.filter((a2) => !q || a2.text.includes(q)).map((a2) => ({ value: a2.value, label: a2.label, hint: a2.hint }));
|
|
7502
|
-
return [...buildRows(ranked, state), ...matchingActions];
|
|
7503
|
-
}
|
|
7504
|
-
}));
|
|
7505
|
-
}, connect = async (profile, state, { interactive, quiet, force }) => {
|
|
7581
|
+
}, pick = (state, initialQuery) => home({
|
|
7582
|
+
message: `Switch to ${ui2.dim("\xB7 type a name, account, role or client")}`,
|
|
7583
|
+
maxItems: Math.max(5, Math.min(14, (process.stdout.rows || 24) - 14)),
|
|
7584
|
+
initialQuery,
|
|
7585
|
+
actions: ACTIONS,
|
|
7586
|
+
rows: (query) => buildRows(rank.rankProfiles(state.profiles, { query, usage: state.settings.usage, current: state.defaultName }), state)
|
|
7587
|
+
}), connect = async (profile, state, { interactive, quiet, force }) => {
|
|
7506
7588
|
let spin = quiet ? null : ui2.spinner(), tryIdentity = async () => {
|
|
7507
7589
|
spin && spin.start(`Connecting to ${profile.name}`);
|
|
7508
7590
|
try {
|
|
@@ -7523,7 +7605,7 @@ ${ui2.dim(viaShortcut ? "Switching clears them from this terminal." : `Unset ${s
|
|
|
7523
7605
|
throw new ui2.CliError(`Logged in, but ${profile.name} still has no access.`, { hint: firstLine(result.message) });
|
|
7524
7606
|
return result;
|
|
7525
7607
|
}, firstLine = (text2) => String(text2 || "").trim().split(`
|
|
7526
|
-
`).filter(Boolean).slice(-1)[0], switchTo = async (profile, state, opts) => {
|
|
7608
|
+
`).filter(Boolean).slice(-1)[0], switchTo = async (profile, state, opts) => (await doSwitch(profile, state, opts), { switched: !0 }), doSwitch = async (profile, state, opts) => {
|
|
7527
7609
|
let { interactive, json } = opts, identity = await connect(profile, state, { interactive, quiet: json, force: opts.force }), [defaultErrors] = await aws.setDefaultProfile(profile.name);
|
|
7528
7610
|
if (defaultErrors)
|
|
7529
7611
|
throw new ui2.CliError(ui2.errorsMessage(defaultErrors));
|
|
@@ -7578,6 +7660,35 @@ ${ui2.dim(`Open a new terminal or run: ${installed.reload}`)}`), installed.name
|
|
|
7578
7660
|
}, runAction = async (key, state, opts) => {
|
|
7579
7661
|
let commands2 = require_commands();
|
|
7580
7662
|
return key == "login" ? commands2.login(state.defaultName, { ...opts, fromPicker: !0 }) : commands2[key](opts.args || [], { ...opts, fromPicker: !0 });
|
|
7663
|
+
}, routeChoice = (choice) => {
|
|
7664
|
+
if (p4.isCancel(choice))
|
|
7665
|
+
return { type: "quit" };
|
|
7666
|
+
let value = String(choice);
|
|
7667
|
+
return value.startsWith(ACTION_PREFIX) ? { type: "page", key: value.slice(ACTION_PREFIX.length) } : { type: "switch", name: value };
|
|
7668
|
+
}, afterPage = (result, err) => err ? err instanceof CancelError2 ? "back" : err instanceof ui2.CliError ? "error" : "throw" : result && result.switched ? "exit" : "home", homeLoop = async (state, opts, initialQuery) => {
|
|
7669
|
+
let first = !0;
|
|
7670
|
+
for (; ; ) {
|
|
7671
|
+
await header(state, { warnings: first });
|
|
7672
|
+
let route = routeChoice(await pick(state, first ? initialQuery : void 0));
|
|
7673
|
+
if (first = !1, route.type == "quit") {
|
|
7674
|
+
p4.outro(ui2.dim(`Bye ${ui2.unicode ? "\u{1F44B}" : ""}`));
|
|
7675
|
+
return;
|
|
7676
|
+
}
|
|
7677
|
+
if (route.type == "switch")
|
|
7678
|
+
return switchTo(state.profiles.find((x2) => x2.name == route.name), state, opts);
|
|
7679
|
+
let result, error;
|
|
7680
|
+
try {
|
|
7681
|
+
result = await runAction(route.key, state, opts);
|
|
7682
|
+
} catch (err) {
|
|
7683
|
+
error = err;
|
|
7684
|
+
}
|
|
7685
|
+
let next = afterPage(result, error);
|
|
7686
|
+
if (next == "exit")
|
|
7687
|
+
return result;
|
|
7688
|
+
if (next == "throw")
|
|
7689
|
+
throw error;
|
|
7690
|
+
next == "back" && p4.cancel(ui2.dim(`${ui2.unicode ? "\u2190" : "<-"} Back`)), next == "error" && ui2.printError(error), state = await loadState();
|
|
7691
|
+
}
|
|
7581
7692
|
}, switchCommand = async (query, opts) => {
|
|
7582
7693
|
let interactive = ui2.isInteractive(opts);
|
|
7583
7694
|
await preflight({ interactive, quiet: opts.json });
|
|
@@ -7598,11 +7709,11 @@ ${ui2.dim(`Open a new terminal or run: ${installed.reload}`)}`), installed.name
|
|
|
7598
7709
|
});
|
|
7599
7710
|
} else if (!interactive)
|
|
7600
7711
|
throw new ui2.CliError("Which profile? Pass its name.", { code: 3, hint: `e.g. switch-profile ${state.profiles[0].name}` });
|
|
7601
|
-
|
|
7602
|
-
let choice = await pick(state, query);
|
|
7603
|
-
return choice.startsWith(ACTION) ? runAction(choice.slice(ACTION.length), state, { ...opts, interactive }) : switchTo(state.profiles.find((x2) => x2.name == choice), state, { ...opts, interactive });
|
|
7712
|
+
return homeLoop(state, { ...opts, interactive }, query);
|
|
7604
7713
|
};
|
|
7605
7714
|
module2.exports = {
|
|
7715
|
+
routeChoice,
|
|
7716
|
+
afterPage,
|
|
7606
7717
|
switchCommand,
|
|
7607
7718
|
switchTo,
|
|
7608
7719
|
connect,
|
|
@@ -7615,7 +7726,7 @@ ${ui2.dim(`Open a new terminal or run: ${installed.reload}`)}`), installed.name
|
|
|
7615
7726
|
// src/commands/index.js
|
|
7616
7727
|
var require_commands = __commonJS({
|
|
7617
7728
|
"src/commands/index.js"(exports2, module2) {
|
|
7618
|
-
var p4 = (init_dist4(), __toCommonJS(
|
|
7729
|
+
var p4 = (init_dist4(), __toCommonJS(dist_exports2)), aws = require_aws(), transforms = require_transforms(), settings2 = require_settings(), shell = require_shell(), migrate = require_migrate(), rank = require_rank(), { resolveLoginMode, isRemoteSession } = require_login(), ui2 = require_ui(), { ask, preflight, loadState, loginKey, describe, loginState, upgradeLegacySso } = require_common(), { ssoLogin, rememberLogin } = require_login_flow(), { switchCommand, switchTo, connect, enableShortcut } = require_switch(), intro2 = (opts) => {
|
|
7619
7730
|
!opts.fromPicker && !opts.json && p4.intro(`${ui2.badge("switch-profile")} ${ui2.dim(settings2.CLI_VERSION)}`);
|
|
7620
7731
|
}, begin = async (opts, { needsInput } = {}) => {
|
|
7621
7732
|
let interactive = ui2.isInteractive(opts);
|
|
@@ -7887,7 +7998,7 @@ AWS recommends SSO or console sign-in instead.`), !await ask(p4.confirm({ messag
|
|
|
7887
7998
|
});
|
|
7888
7999
|
|
|
7889
8000
|
// src/cli.js
|
|
7890
|
-
var { Command } = require_commander(), p3 = (init_dist4(), __toCommonJS(
|
|
8001
|
+
var { Command } = require_commander(), p3 = (init_dist4(), __toCommonJS(dist_exports2)), ui = require_ui(), { CLI_VERSION } = require_settings(), { CancelError } = require_common(), commands = require_commands();
|
|
7891
8002
|
process.env.AWS_CLI_AGENT_TOOLKIT_HINT_DISABLED = "true";
|
|
7892
8003
|
var EXAMPLES = `
|
|
7893
8004
|
Examples:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switch-profile",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"switch-profile": "index.js"
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"author": "Nicolas Dao",
|
|
37
37
|
"license": "BSD-3-Clause",
|
|
38
38
|
"devDependencies": {
|
|
39
|
+
"@clack/core": "^1.5.1",
|
|
39
40
|
"@clack/prompts": "^1.8.1",
|
|
40
41
|
"@eslint/js": "^10.0.1",
|
|
41
42
|
"chai": "^4.1.2",
|