switch-profile 0.1.1 → 0.2.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.2.1](https://github.com/nicolasdao/switch-profile/compare/v0.2.0...v0.2.1) (2026-02-08)
6
+
7
+ ## [0.2.0](https://github.com/nicolasdao/switch-profile/compare/v0.1.2...v0.2.0) (2026-02-08)
8
+
9
+
10
+ ### Bug Fixes
11
+
12
+ * handle SSO profile creation failure and improve SSO setup UX ([b0ee837](https://github.com/nicolasdao/switch-profile/commit/b0ee83791bfbc1208cc5fb6b6f2850d4cbd160c9))
13
+ * vulnerabilities ([3fa2575](https://github.com/nicolasdao/switch-profile/commit/3fa2575156f3e07a6de9cd077f3f8f75f9bceafa))
14
+
15
+ ### [0.1.2](https://github.com/nicolasdao/switch-profile/compare/v0.1.1...v0.1.2) (2022-05-14)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * Multiple SSO profiles are not supported. It only uses one. ([b9d9d03](https://github.com/nicolasdao/switch-profile/commit/b9d9d03b4edfa048cc157376222378513138e257))
21
+
5
22
  ### [0.1.1](https://github.com/nicolasdao/switch-profile/compare/v0.1.0...v0.1.1) (2021-08-03)
6
23
 
7
24
 
package/README.md CHANGED
@@ -1,43 +1,157 @@
1
1
  # switch-profile
2
2
 
3
- Switch between AWS profiles without having to manually edit the `.aws/credentials` or the environment variables.
3
+ An interactive CLI tool for switching between AWS profiles directly from your terminal. No more manually editing `~/.aws/credentials` or juggling environment variables.
4
4
 
5
+ ```shell
6
+ npx switch-profile
7
+ ```
8
+
9
+ ## Why?
10
+
11
+ AWS SSO credentials expire every hour. Without `switch-profile`, refreshing them means either:
12
+
13
+ 1. **Manual copy-paste** - Browse to the SSO portal, log in, reveal credentials, paste them into your terminal or `~/.aws/credentials` file. Repeat every hour.
14
+ 2. **Per-command `--profile` flag** - Use `aws sso login --profile <name>`, but then every command (and every tool like Terraform) needs `--profile`. Not always possible or practical.
15
+
16
+ `switch-profile` makes setting any AWS profile as `default` trivial - one command, pick from a list, done. It handles SSO session refresh automatically, including opening the browser for re-authentication when sessions expire.
17
+
18
+ ## Prerequisites
19
+
20
+ - **[AWS CLI v2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)** - Version 2 or later is required.
21
+ - **Node.js** - Any recent version that supports `npx`.
22
+
23
+ > **Important:** Remove these environment variables from your shell if they are set, as they override the default profile and will conflict with `switch-profile`:
24
+ > - `AWS_ACCESS_KEY_ID`
25
+ > - `AWS_SECRET_ACCESS_KEY`
26
+ > - `AWS_SESSION_TOKEN`
27
+
28
+ ## Installation
29
+
30
+ No installation needed. Run directly with npx:
31
+
32
+ ```shell
33
+ npx switch-profile
34
+ ```
35
+
36
+ Or install globally:
37
+
38
+ ```shell
39
+ npm install -g switch-profile
40
+ switch-profile
41
+ ```
42
+
43
+ ## Quick Start
44
+
45
+ ### Switch between existing profiles
46
+
47
+ ```shell
48
+ npx switch-profile
49
+ ```
50
+
51
+ This will:
52
+ 1. Show your current default profile with its expiry status.
53
+ 2. List all available profiles.
54
+ 3. Let you pick one to set as the new `default`.
55
+
56
+ For SSO profiles, if the session has expired, it automatically opens your browser for re-authentication.
57
+
58
+ ### Create a new profile
59
+
60
+ ```shell
61
+ npx switch-profile
62
+ # Select "More options" > "Create profile"
5
63
  ```
64
+
65
+ You can create:
66
+ - **Standard profiles** - Access key + secret key pair.
67
+ - **SSO profiles** - Launches the interactive `aws configure sso` flow.
68
+
69
+ ### Delete profiles
70
+
71
+ ```shell
6
72
  npx switch-profile
73
+ # Select "More options" > "Delete profiles"
7
74
  ```
8
75
 
9
- This terminal utility helps switching between AWS CLI profiles. It sets the `default` profile by editing the `.aws/credentials` file. It requires `AWS CLI v2` to be installed.
76
+ Select one or more profiles to remove. The current default profile cannot be deleted (switch to another one first).
77
+
78
+ ### Refresh an expired profile
79
+
80
+ ```shell
81
+ npx switch-profile
82
+ # Select "More options" > "Refresh default profile"
83
+ ```
84
+
85
+ This option only appears when the current default profile has expired. It forces a new SSO login and refreshes the credentials.
86
+
87
+ ## How It Works
88
+
89
+ `switch-profile` manages two AWS configuration files:
90
+
91
+ | File | Purpose |
92
+ |------|---------|
93
+ | `~/.aws/config` | Stores profile settings (region, output format, SSO metadata) |
94
+ | `~/.aws/credentials` | Stores access keys, secret keys, and session tokens |
10
95
 
11
- This utility also supports creating new AWS profiles, including SSO profiles as well as deleting them.
96
+ When you select a profile, `switch-profile`:
97
+ 1. Retrieves the credentials for that profile (from cache or via SSO login).
98
+ 2. Writes them into the `[default]` section of both files.
99
+ 3. Records the profile name and expiry date for status display.
12
100
 
13
- > WARNING: Make sure that the following environment variables have been removed from your path, otherwise, they will conflict with the default AWS CLI profile:
14
- > - `AWS_ACCESS_KEY_ID`
15
- > - `AWS_SECRET_ACCESS_KEY`
16
- > - `AWS_SESSION_TOKEN`
101
+ For SSO profiles specifically, it leverages two additional AWS CLI cache directories:
102
+ - `~/.aws/sso/cache/` - SSO session tokens (long-lived, ~24 hours)
103
+ - `~/.aws/cli/cache/` - Temporary AWS credentials (short-lived, ~1 hour)
17
104
 
18
- # Why using this utility?
105
+ ## Detailed Documentation
19
106
 
20
- `switch-profile` was originally created to refresh short-lived AWS SSO profiles in the terminal and set them as default. Indeed, as of 2021, the only two ways to set up a short-lived SSO profile as default in the terminal are:
21
- - Manually paste the short-lived credentials in the terminal:
22
- - Browse to the AWS SSO login page and login.
23
- - Select an account.
24
- - Reveal the short-lived credentials (i.e., AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN).
25
- - Copy paste them in the terminal or manually edit the `.aws/credentials` file.
26
- - Create an SSO profile in the terminal and update its credentials via the CLI:
27
- - Creating an SSO profile: `aws configure sso`
28
- - Renew a SSO credentials for a specific profile: `aws sso login --profile YOUR_PROFILE`
107
+ For deeper technical details, see the docs below:
29
108
 
30
- The issue with the first method is that you have to repeat it every hour, which can make long days feel even longer. The issue with the second method is that it requires your code or third party app (e.g, Terraform) to support the `--profile` option. There are scenarios where using this `--profile` option is either not possible or impractical (often impractical as this may mean all engineers should agree to use the same convention for the profile's name).
109
+ | Document | Description |
110
+ |----------|-------------|
111
+ | [Architecture](docs/architecture.md) | Project structure, source files, and how the components fit together |
112
+ | [AWS Profile Management](docs/aws-profile-management.md) | How AWS profiles, SSO sessions, and credentials are managed internally |
113
+ | [CLI Interface](docs/cli-interface.md) | Detailed walkthrough of every menu, prompt, and user flow |
114
+ | [Configuration Files](docs/configuration-files.md) | Exact formats of all AWS and internal configuration files |
115
+ | [Development Guide](docs/development-guide.md) | How to set up, develop, test, lint, and release |
31
116
 
32
- `switch-profile` aims to solve those issues by making setting any profile as `default` trivial.
117
+ ## Troubleshooting
33
118
 
34
- # Extra features
119
+ ### `invalid_grant: Invalid grant provided`
120
+
121
+ This error occurs during SSO profile creation when the **wrong SSO region** is specified. AWS SSO is region-specific - you must use the region where your SSO instance is configured, not the region you want to deploy resources to.
122
+
123
+ **Fix:** Delete the profile and recreate it with the correct SSO region.
124
+
125
+ ### `Error: Fail to get credentials for profile ... Error loading SSO Token...`
126
+
127
+ This typically happens after the `~/.aws/sso/cache` folder has been deleted or corrupted. This folder tracks SSO sessions and cannot be reconstructed automatically.
128
+
129
+ **Fix:** Delete the affected SSO profiles and recreate them:
130
+
131
+ 1. Run `npx switch-profile`
132
+ 2. Select **More options** > **Delete profiles**
133
+ 3. Remove the broken SSO profiles
134
+ 4. Recreate them via **More options** > **Create profile**
135
+
136
+ ### AWS CLI not found
137
+
138
+ `switch-profile` requires AWS CLI v2. Install it for your platform:
139
+
140
+ **macOS:**
141
+ ```shell
142
+ brew install awscli
143
+ brew link --overwrite awscli
144
+ ```
145
+
146
+ **Linux:**
147
+ ```shell
148
+ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
149
+ unzip awscliv2.zip
150
+ sudo ./aws/install
151
+ ```
35
152
 
36
- The `More options` supports the following:
37
- - `Create profile`: Helps create both a standard or AWS SSO profile.
38
- - `Delete profiles`: Helps cleaning one or many profiles.
39
- - `Refresh default profile`: Helps refreshing the current default profile if it has expired (e.g., SSO profile). This option only appears when the default profile has expired.
153
+ **Windows:** Download and run the [AWS CLI MSI installer](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).
40
154
 
41
- # License
155
+ ## License
42
156
 
43
- BSD 3-Clause License
157
+ [BSD 3-Clause](LICENSE)
@@ -0,0 +1,185 @@
1
+ # Architecture
2
+
3
+ This document describes the project structure, source files, and how the components fit together.
4
+
5
+ ## Project Structure
6
+
7
+ ```
8
+ switch-profile/
9
+ ├── index.js # CLI entry point (executable)
10
+ ├── package.json # Project manifest
11
+ ├── CHANGELOG.md # Auto-generated release notes
12
+ ├── LICENSE # BSD 3-Clause
13
+ ├── src/
14
+ │ ├── core.js # Shell execution and error formatting
15
+ │ ├── fileHelper.js # File system operations
16
+ │ └── aws/
17
+ │ ├── index.js # AWS profile and credential management
18
+ │ └── regions.js # AWS region definitions
19
+ └── test/
20
+ └── index.js # Test suite
21
+ ```
22
+
23
+ ## Component Overview
24
+
25
+ ### `index.js` - CLI Entry Point
26
+
27
+ The main executable file (with `#!/usr/bin/env node` shebang). Registered as the `bin` target in `package.json`, so it runs when you invoke `switch-profile` or `npx switch-profile`.
28
+
29
+ **Responsibilities:**
30
+ - Defines the CLI command structure using [Commander.js](https://www.npmjs.com/package/commander).
31
+ - Renders interactive prompts using [Inquirer.js](https://www.npmjs.com/package/inquirer).
32
+ - Orchestrates the user flow: profile listing, selection, creation, deletion, and refresh.
33
+ - Displays colored status output (expiry warnings, success messages).
34
+
35
+ **Key functions:**
36
+
37
+ | Function | Purpose |
38
+ |----------|---------|
39
+ | `switchCmd()` | Main command handler. Checks AWS CLI, shows current profile status, lists profiles, renders the selection menu. |
40
+ | `setProfileToDefault(name, list, msg)` | Gets credentials for a profile, writes them as the `[default]` profile. Shows a clear error if the profile is not found in the list. |
41
+ | `createNewProfile(profiles, makeItDefault)` | Walks the user through creating a standard or SSO profile. Displays an SSO Setup Guide before SSO creation and checks for errors before reporting success. |
42
+ | `chooseProfileName(denyList)` | Validates profile name input (lowercase alphanumeric, dashes, underscores, min 2 chars, no duplicates). |
43
+ | `chooseRegions()` | Autocomplete region picker from the 24 supported AWS regions. |
44
+ | `chooseNonEmpty(prop, message)` | Generic required-field input validator. |
45
+
46
+ **Default command behavior:** If no command is passed (`process.argv.length == 2`), it automatically injects the `switch` command.
47
+
48
+ ### `src/aws/index.js` - AWS Profile Management
49
+
50
+ The core module. Handles all interactions with AWS configuration files and the AWS CLI.
51
+
52
+ **Responsibilities:**
53
+ - Reading and writing `~/.aws/config` and `~/.aws/credentials`.
54
+ - Parsing INI-style profile sections.
55
+ - Managing SSO sessions and credential caching.
56
+ - Creating, deleting, and listing profiles.
57
+ - Refreshing expired SSO sessions (including browser redirect).
58
+
59
+ See [AWS Profile Management](aws-profile-management.md) for a detailed breakdown of every function.
60
+
61
+ ### `src/aws/regions.js` - Region Definitions
62
+
63
+ A static array of 24 AWS region objects, each with `name` and `code` properties:
64
+
65
+ ```javascript
66
+ { name: 'US East (N. Virginia)', code: 'us-east-1' }
67
+ ```
68
+
69
+ Regions covered: 4 US, 8 Asia Pacific, 6 EU, 2 China, 2 GovCloud, 1 Africa, 1 Canada, 1 Middle East, 1 South America.
70
+
71
+ ### `src/core.js` - Shell Execution and Error Formatting
72
+
73
+ Low-level utilities shared across the project.
74
+
75
+ | Function | Purpose |
76
+ |----------|---------|
77
+ | `exec(cmd)` | Wraps `child_process.exec()` in a Promise. Rejects on error or stderr. |
78
+ | `isCommandExist(cmd, errorMsg)` | Returns a function that checks if `cmd` exists in PATH (uses `which` on Unix, `where` on Windows). Results are cached. |
79
+ | `printErrors(errors, options)` | Prints an array of `Error` objects in red. |
80
+ | `printAWSerrors(errors, options)` | Like `printErrors` but detects missing AWS CLI and appends installation hints. |
81
+ | `formatErrorMsg(errors, options)` | Formats error arrays into a single message string. Supports `noStack` option. |
82
+
83
+ ### `src/fileHelper.js` - File System Operations
84
+
85
+ A general-purpose file I/O library. Only a subset of its functions are used by `switch-profile`:
86
+
87
+ **Used by the project:**
88
+
89
+ | Function | Exported As | Purpose |
90
+ |----------|-------------|---------|
91
+ | `fileExists(path)` | `exists` | Check if a file or folder exists |
92
+ | `readFile(path)` | `read` | Read file contents into a Buffer |
93
+ | `writeToFile(path, content, opts)` | `write` | Create or overwrite a file |
94
+ | `listFiles(folder, opts)` | `list` | Glob-based file listing |
95
+ | `getJSON(path, default)` | `json.get` | Read and parse a JSON file |
96
+
97
+ **Available but unused:**
98
+
99
+ Functions for folder creation/deletion, MIME type detection, ZIP/TAR archiving, and more. These exist because `fileHelper.js` is a shared utility library.
100
+
101
+ ## Dependency Graph
102
+
103
+ ```
104
+ index.js
105
+ ├── commander (CLI framework)
106
+ ├── inquirer (interactive prompts)
107
+ ├── inquirer-autocomplete-prompt
108
+ ├── colors (terminal colors)
109
+ ├── src/core.js
110
+ │ ├── colors
111
+ │ ├── puffy (error handling: catchErrors, wrapErrors)
112
+ │ └── child_process (Node built-in)
113
+ ├── src/aws/index.js
114
+ │ ├── puffy (error handling + delay)
115
+ │ ├── src/core.js
116
+ │ ├── src/fileHelper.js
117
+ │ │ ├── core-async (co-routine support)
118
+ │ │ ├── fast-glob (file pattern matching)
119
+ │ │ ├── rimraf (recursive delete)
120
+ │ │ ├── mime-types (MIME detection)
121
+ │ │ ├── archiver (ZIP creation - unused)
122
+ │ │ ├── tar-stream (TAR creation - unused)
123
+ │ │ └── convert-stream (stream utils - unused)
124
+ │ ├── src/aws/regions.js
125
+ │ └── child_process (for spawn)
126
+ └── package.json (version number)
127
+ ```
128
+
129
+ ## Error Handling Pattern
130
+
131
+ All async functions in the AWS module use the `catchErrors` wrapper from the `puffy` library. This converts thrown errors into a `[errors, result]` tuple:
132
+
133
+ ```javascript
134
+ const [errors, profiles] = await listProfiles()
135
+ if (errors) {
136
+ printAWSerrors([new Error('Fail to list profiles'), ...errors])
137
+ return
138
+ }
139
+ // Use profiles safely
140
+ ```
141
+
142
+ Errors are composed using `wrapErrors(message, errorArray)` to build layered error contexts:
143
+
144
+ ```
145
+ Error: Fail to get credentials for profile sso-dev
146
+ → Error: Fail to refresh the SSO session
147
+ → Error: Timeout - Time to wait exceeded 300000ms
148
+ ```
149
+
150
+ This pattern allows errors to propagate up with context while keeping individual functions simple.
151
+
152
+ ## Data Flow
153
+
154
+ ```
155
+ User runs: npx switch-profile
156
+ │
157
+ ▼
158
+ ┌──────────────┐
159
+ │ index.js │ Checks AWS CLI v2 exists
160
+ │ switchCmd() │ Gets default profile + status
161
+ │ │ Lists all profiles
162
+ └──────┬───────┘
163
+ │
164
+ ▼
165
+ User selects a profile
166
+ │
167
+ ▼
168
+ ┌──────────────────────┐
169
+ │ setProfileToDefault │
170
+ │ │
171
+ │ 1. Find profile │
172
+ │ 2. Get credentials │──────► For SSO: refresh session,
173
+ │ 3. Update default │ open browser if needed
174
+ └──────────────────────┘
175
+ │
176
+ ▼
177
+ ┌──────────────────────┐
178
+ │ updateDefaultProfile│
179
+ │ │
180
+ │ Writes [default] │
181
+ │ section to: │
182
+ │ - ~/.aws/credentials│
183
+ │ - ~/.aws/config │
184
+ └──────────────────────┘
185
+ ```