az2aws 1.3.0 → 1.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.4.0](https://github.com/kuma0128/az2aws/compare/v1.3.0...v1.4.0) (2026-02-12)
4
+
5
+
6
+ ### Features
7
+
8
+ * add GovCloud region warning ([#104](https://github.com/kuma0128/az2aws/issues/104)) ([1e169cc](https://github.com/kuma0128/az2aws/commit/1e169cc77c35a5453728f71952aa4201842c8430))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * honor http_proxy for browser and STS ([#92](https://github.com/kuma0128/az2aws/issues/92)) ([0e002ae](https://github.com/kuma0128/az2aws/commit/0e002ae362466cd9434bb364150bf54227738225))
14
+
15
+
16
+ ### Performance Improvements
17
+
18
+ * optimize keyboard input clearing with select + backspace ([#116](https://github.com/kuma0128/az2aws/issues/116)) ([84b4cfb](https://github.com/kuma0128/az2aws/commit/84b4cfbef32917a6f6d2f9ef56d5a13b09a91f3a))
19
+ * replace lodash with native array methods ([#115](https://github.com/kuma0128/az2aws/issues/115)) ([f61786f](https://github.com/kuma0128/az2aws/commit/f61786f0ab1f215d351fe3ddba15d22cfb048198))
20
+
3
21
  ## [1.3.0](https://github.com/kuma0128/az2aws/compare/v1.2.0...v1.3.0) (2026-01-27)
4
22
 
5
23
 
package/CONTRIBUTING.md CHANGED
@@ -49,10 +49,10 @@ mise use --global node@24
49
49
  node -v
50
50
  ```
51
51
 
52
- 5. Install yarn:
52
+ 5. Enable pnpm via corepack:
53
53
 
54
54
  ```sh
55
- npm install -g yarn
55
+ corepack enable
56
56
  ```
57
57
 
58
58
  ### Setup
@@ -67,32 +67,33 @@ cd az2aws
67
67
  2. Install dependencies:
68
68
 
69
69
  ```sh
70
- yarn install
70
+ pnpm install
71
71
  ```
72
72
 
73
73
  3. Start development mode:
74
74
 
75
75
  ```sh
76
- yarn start
76
+ pnpm start
77
77
  ```
78
78
 
79
79
  Or build and run production mode:
80
80
 
81
81
  ```sh
82
- yarn build && node ./lib/index.js
82
+ pnpm build && node ./lib/index.js
83
83
  ```
84
84
 
85
85
  ### Available Scripts
86
86
 
87
87
  | Script | Description |
88
88
  |--------|-------------|
89
- | `yarn start` | Start development mode with hot reload |
90
- | `yarn build` | Build for production |
91
- | `yarn test` | Run linting and formatting checks |
92
- | `yarn test:unit` | Run unit tests |
93
- | `yarn eslint` | Run ESLint |
94
- | `yarn prettier:check` | Check code formatting |
95
- | `yarn prettier:write` | Auto-fix code formatting |
89
+ | `pnpm start` | Start development mode with hot reload |
90
+ | `pnpm build` | Build for production |
91
+ | `pnpm test` | Run unit tests |
92
+ | `pnpm test:coverage` | Run unit tests with coverage |
93
+ | `pnpm lint` | Run ESLint and formatting checks |
94
+ | `pnpm eslint` | Run ESLint |
95
+ | `pnpm prettier:check` | Check code formatting |
96
+ | `pnpm prettier:write` | Auto-fix code formatting |
96
97
 
97
98
  ## Development Workflow
98
99
 
@@ -107,7 +108,7 @@ git checkout -b fix/your-bug-fix
107
108
  2. Make your changes and ensure tests pass:
108
109
 
109
110
  ```sh
110
- yarn test
111
+ pnpm test
111
112
  ```
112
113
 
113
114
  3. Commit your changes following our [commit message guidelines](#commit-message-guidelines).
@@ -118,8 +119,8 @@ yarn test
118
119
 
119
120
  ### Before Submitting
120
121
 
121
- - [ ] Run `yarn test` and ensure all checks pass
122
- - [ ] Run `yarn build` to verify the build succeeds
122
+ - [ ] Run `pnpm test` and ensure all checks pass
123
+ - [ ] Run `pnpm build` to verify the build succeeds
123
124
  - [ ] Update documentation if you changed any user-facing behavior
124
125
  - [ ] Add tests for new functionality
125
126
 
@@ -164,13 +165,13 @@ This project uses ESLint and Prettier. Your code will be automatically checked.
164
165
 
165
166
  ```sh
166
167
  # Check formatting
167
- yarn prettier:check
168
+ pnpm prettier:check
168
169
 
169
170
  # Auto-fix formatting
170
- yarn prettier:write
171
+ pnpm prettier:write
171
172
 
172
173
  # Run linter
173
- yarn eslint
174
+ pnpm eslint
174
175
  ```
175
176
 
176
177
  ### File Organization
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  [![view on npm](http://img.shields.io/npm/v/az2aws.svg)](https://www.npmjs.org/package/az2aws)
2
- [![npm module downloads per month](http://img.shields.io/npm/dm/az2aws.svg)](https://www.npmjs.org/package/az2aws)
2
+ [![npm module downloads per month](http://img.shields.io/npm/dm/az2aws.svg?cacheSeconds=86400)](https://www.npmjs.org/package/az2aws)
3
3
  [![CI](https://github.com/kuma0128/az2aws/actions/workflows/main.yml/badge.svg)](https://github.com/kuma0128/az2aws/actions/workflows/main.yml)
4
4
  [![codecov](https://codecov.io/gh/kuma0128/az2aws/graph/badge.svg)](https://codecov.io/gh/kuma0128/az2aws)
5
5
 
@@ -121,6 +121,10 @@ Set the `region` in your ~/.aws/config to use non-standard AWS partitions:
121
121
  - **GovCloud**: us-gov-west-1, us-gov-east-1
122
122
  - **China**: cn-north-1, cn-northwest-1
123
123
 
124
+ For GovCloud, make sure your AWS CLI default region is set to a GovCloud
125
+ region if you do not set a profile region; otherwise STS calls may target the
126
+ standard partition.
127
+
124
128
  #### Stay Logged In
125
129
 
126
130
  Enable "Stay logged in" during configuration to use `--no-prompt` without storing passwords:
@@ -178,7 +182,7 @@ You'll be prompted for username, password, and MFA if required. After login, use
178
182
  **Tips:**
179
183
  - Set `AWS_PROFILE` env var instead of using `--profile`
180
184
  - Use `--mode gui --disable-gpu` on VMs or if rendering fails
181
- - Set `https_proxy` env var for corporate proxy
185
+ - Set `https_proxy` or `http_proxy` env var for corporate proxy
182
186
 
183
187
  #### Troubleshooting
184
188
 
package/lib/awsConfig.js CHANGED
@@ -47,6 +47,11 @@ exports.awsConfig = {
47
47
  expirationDate = new Date(config[profileName].aws_expiration);
48
48
  }
49
49
  const timeDifference = expirationDate.getTime() - new Date().getTime();
50
+ // If expiration date is invalid (NaN), treat as expired for safety
51
+ if (isNaN(timeDifference)) {
52
+ debug("Invalid expiration date, treating as expired");
53
+ return true;
54
+ }
50
55
  debug(`Remaining time till credential expiration: ${timeDifference / 1000}s, refresh due if time lower than: ${refreshLimitInMs / 1000}s`);
51
56
  return timeDifference < refreshLimitInMs;
52
57
  },
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.configureProfileAsync = void 0;
6
+ exports.configureProfileAsync = configureProfileAsync;
7
7
  const inquirer_1 = __importDefault(require("inquirer"));
8
8
  const awsConfig_1 = require("./awsConfig");
9
9
  async function configureProfileAsync(profileName) {
@@ -74,4 +74,3 @@ async function configureProfileAsync(profileName) {
74
74
  });
75
75
  console.log("Profile saved.");
76
76
  }
77
- exports.configureProfileAsync = configureProfileAsync;
package/lib/login.js CHANGED
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.login = void 0;
7
- const lodash_1 = __importDefault(require("lodash"));
8
7
  const bluebird_1 = __importDefault(require("bluebird"));
9
8
  const inquirer_1 = __importDefault(require("inquirer"));
10
9
  const zlib_1 = __importDefault(require("zlib"));
@@ -19,6 +18,7 @@ const awsConfig_1 = require("./awsConfig");
19
18
  const https_proxy_agent_1 = require("https-proxy-agent");
20
19
  const paths_1 = require("./paths");
21
20
  const mkdirp_1 = __importDefault(require("mkdirp"));
21
+ const promises_1 = __importDefault(require("fs/promises"));
22
22
  const https_1 = require("https");
23
23
  const node_http_handler_1 = require("@smithy/node-http-handler");
24
24
  const loginStates_1 = require("./loginStates");
@@ -32,6 +32,10 @@ const AZURE_AD_SSO = "autologon.microsoftazuread-sso.com";
32
32
  const AWS_SAML_ENDPOINT = "https://signin.aws.amazon.com/saml";
33
33
  const AWS_CN_SAML_ENDPOINT = "https://signin.amazonaws.cn/saml";
34
34
  const AWS_GOV_SAML_ENDPOINT = "https://signin.amazonaws-us-gov.com/saml";
35
+ const getProxyUrl = () => process.env.https_proxy ||
36
+ process.env.HTTPS_PROXY ||
37
+ process.env.http_proxy ||
38
+ process.env.HTTP_PROXY;
35
39
  exports.login = {
36
40
  async loginAsync(profileName, mode, disableSandbox, noPrompt, enableChromeNetworkService, awsNoVerifySsl, enableChromeSeamlessSso, noDisableExtensions, disableGpu) {
37
41
  let headless, cliProxy;
@@ -208,8 +212,9 @@ exports.login = {
208
212
  args.push(`--profile-directory=${paths_1.paths.profileDir}`);
209
213
  }
210
214
  }
211
- if (process.env.https_proxy) {
212
- args.push(`--proxy-server=${process.env.https_proxy}`);
215
+ const proxyUrl = getProxyUrl();
216
+ if (proxyUrl) {
217
+ args.push(`--proxy-server=${proxyUrl}`);
213
218
  }
214
219
  const ignoreDefaultArgs = noDisableExtensions
215
220
  ? ["--disable-extensions"]
@@ -225,7 +230,24 @@ exports.login = {
225
230
  if (paths_1.paths.chromeBin) {
226
231
  launchParams.executablePath = paths_1.paths.chromeBin;
227
232
  }
228
- browser = await puppeteer_1.default.launch(launchParams);
233
+ try {
234
+ browser = await puppeteer_1.default.launch(launchParams);
235
+ }
236
+ catch (e) {
237
+ if (e instanceof Error &&
238
+ e.constructor.name === "TargetCloseError" &&
239
+ rememberMe) {
240
+ const userDataDir = paths_1.paths.userDataDir || paths_1.paths.chromium;
241
+ debug(`Browser launch failed with TargetCloseError. Resetting profile at ${userDataDir}`);
242
+ console.warn("Browser profile appears incompatible. Resetting profile data and retrying...");
243
+ await promises_1.default.rm(userDataDir, { recursive: true, force: true });
244
+ await (0, mkdirp_1.default)(userDataDir);
245
+ browser = await puppeteer_1.default.launch(launchParams);
246
+ }
247
+ else {
248
+ throw e;
249
+ }
250
+ }
229
251
  // Wait for a bit as sometimes the browser isn't ready.
230
252
  await bluebird_1.default.delay(200);
231
253
  const pages = await browser.pages();
@@ -417,7 +439,7 @@ exports.login = {
417
439
  if (!defaultRoleArn) {
418
440
  throw new CLIError_1.CLIError("--no-prompt requires azure_default_role_arn when multiple roles are available.");
419
441
  }
420
- role = lodash_1.default.find(roles, ["roleArn", defaultRoleArn]);
442
+ role = roles.find((r) => r.roleArn === defaultRoleArn);
421
443
  if (!role) {
422
444
  throw new CLIError_1.CLIError(`Default role ARN '${defaultRoleArn}' was not found in the SAML response.`);
423
445
  }
@@ -429,7 +451,7 @@ exports.login = {
429
451
  name: "role",
430
452
  message: "Role:",
431
453
  type: "list",
432
- choices: lodash_1.default.sortBy(lodash_1.default.map(roles, "roleArn")),
454
+ choices: roles.map((r) => r.roleArn).sort(),
433
455
  default: defaultRoleArn,
434
456
  });
435
457
  }
@@ -461,7 +483,7 @@ exports.login = {
461
483
  if (questions.length > 0) {
462
484
  const answers = await inquirer_1.default.prompt(questions);
463
485
  if (!role)
464
- role = lodash_1.default.find(roles, ["roleArn", answers.role]);
486
+ role = roles.find((r) => r.roleArn === answers.role);
465
487
  if (answers.durationHours) {
466
488
  durationHours = parseInt(answers.durationHours, 10);
467
489
  }
@@ -491,12 +513,13 @@ exports.login = {
491
513
  "This makes the connection vulnerable to MITM attacks. " +
492
514
  "Consider using NODE_EXTRA_CA_CERTS environment variable instead.");
493
515
  }
494
- if (process.env.https_proxy) {
516
+ const proxyUrl = getProxyUrl();
517
+ if (proxyUrl) {
495
518
  const proxyOptions = awsNoVerifySsl ? { rejectUnauthorized: false } : {};
496
519
  stsOptions = {
497
520
  ...stsOptions,
498
521
  requestHandler: new node_http_handler_1.NodeHttpHandler({
499
- httpsAgent: new https_proxy_agent_1.HttpsProxyAgent(process.env.https_proxy, proxyOptions),
522
+ httpsAgent: new https_proxy_agent_1.HttpsProxyAgent(proxyUrl, proxyOptions),
500
523
  }),
501
524
  };
502
525
  }
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.states = void 0;
7
- const lodash_1 = __importDefault(require("lodash"));
8
7
  const bluebird_1 = __importDefault(require("bluebird"));
9
8
  const inquirer_1 = __importDefault(require("inquirer"));
10
9
  const debug_1 = __importDefault(require("debug"));
@@ -54,9 +53,10 @@ exports.states = [
54
53
  debug("Focusing on username input");
55
54
  await page.focus(`input[name="loginfmt"]`);
56
55
  debug("Clearing input");
57
- for (let i = 0; i < 100; i++) {
58
- await page.keyboard.press("Backspace");
59
- }
56
+ await page.$eval('input[name="loginfmt"]', (el) => {
57
+ el.select();
58
+ });
59
+ await page.keyboard.press("Backspace");
60
60
  debug("Typing username");
61
61
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
62
62
  await page.keyboard.type(username);
@@ -116,11 +116,11 @@ exports.states = [
116
116
  name: "account",
117
117
  message: "Account:",
118
118
  type: "list",
119
- choices: lodash_1.default.map(accounts, "message"),
119
+ choices: accounts.map((a) => a.message),
120
120
  default: aadTileMessage,
121
121
  },
122
122
  ]);
123
- account = lodash_1.default.find(accounts, ["message", answers.account]);
123
+ account = accounts.find((a) => a.message === answers.account);
124
124
  }
125
125
  if (!account) {
126
126
  throw new Error("Unable to find account");
@@ -281,9 +281,10 @@ exports.states = [
281
281
  debug("Focusing on verification code input");
282
282
  await page.focus(`input[name="otc"]`);
283
283
  debug("Clearing input");
284
- for (let i = 0; i < 100; i++) {
285
- await page.keyboard.press("Backspace");
286
- }
284
+ await page.$eval('input[name="otc"]', (el) => {
285
+ el.select();
286
+ });
287
+ await page.keyboard.press("Backspace");
287
288
  debug("Typing verification code");
288
289
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
289
290
  await page.keyboard.type(verificationCode);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "az2aws",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Use Azure AD SSO to log into the AWS CLI. A modern, actively maintained alternative to aws-azure-login.",
5
5
  "main": "index.js",
6
6
  "author": {
@@ -37,6 +37,13 @@
37
37
  "engines": {
38
38
  "node": ">=24.0"
39
39
  },
40
+ "packageManager": "pnpm@10.29.3",
41
+ "pnpm": {
42
+ "onlyBuiltDependencies": [
43
+ "esbuild",
44
+ "puppeteer"
45
+ ]
46
+ },
40
47
  "bin": {
41
48
  "az2aws": "lib/index.js"
42
49
  },
@@ -50,7 +57,7 @@
50
57
  "test": "vitest run",
51
58
  "test:watch": "vitest",
52
59
  "test:coverage": "vitest run --coverage",
53
- "lint": "yarn eslint && yarn prettier:check"
60
+ "lint": "pnpm eslint && pnpm prettier:check"
54
61
  },
55
62
  "dependencies": {
56
63
  "@aws-sdk/client-sts": "^3.723.0",
@@ -63,7 +70,6 @@
63
70
  "https-proxy-agent": "^7.0.6",
64
71
  "ini": "^3.0.1",
65
72
  "inquirer": "^8.2.6",
66
- "lodash": "^4.17.21",
67
73
  "mkdirp": "^2.1.6",
68
74
  "puppeteer": "^24.34.0",
69
75
  "uuid": "^9.0.1"
@@ -74,7 +80,6 @@
74
80
  "@types/debug": "^4.1.12",
75
81
  "@types/ini": "^1.3.34",
76
82
  "@types/inquirer": "^8.2.10",
77
- "@types/lodash": "^4.17.0",
78
83
  "@types/mkdirp": "^1.0.2",
79
84
  "@types/node": "^24.0.0",
80
85
  "@types/uuid": "^8.3.4",
@@ -1,3 +0,0 @@
1
- {
2
- ".": "1.3.0"
3
- }