ag-awsauth 0.0.293 → 0.0.294

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.
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.allowAccessIfRequested = exports.dismissAllowAccessPrompt = exports.allowAccessSelectors = exports.goToPage = exports.launchBrowser = exports.closeBrowser = void 0;
13
13
  exports.getMFA = getMFA;
14
14
  const log_1 = require("ag-common/dist/common/helpers/log");
15
+ const sleep_1 = require("ag-common/dist/common/helpers/sleep");
15
16
  const puppeteer_1 = require("puppeteer");
16
17
  const __1 = require("..");
17
18
  const config_1 = require("../config");
@@ -103,9 +104,7 @@ const clickSelectorIfPresent = (page_1, selector_1, ...args_1) => __awaiter(void
103
104
  catch (_a) {
104
105
  // Element may detach between query and click (SPA re-render).
105
106
  // Fall back to an in-page click which re-queries the selector.
106
- yield page
107
- .$eval(selector, (bn) => bn.click())
108
- .catch(() => undefined);
107
+ yield page.$eval(selector, (bn) => bn.click()).catch(() => undefined);
109
108
  }
110
109
  return true;
111
110
  }
@@ -113,24 +112,23 @@ const clickSelectorIfPresent = (page_1, selector_1, ...args_1) => __awaiter(void
113
112
  return false;
114
113
  }
115
114
  });
116
- const clickAllowAccessByText = (page) => __awaiter(void 0, void 0, void 0, function* () {
115
+ const clickAllowAccessByText = (page) => {
117
116
  try {
118
- return yield page.evaluate(() => {
117
+ const clicked = page.evaluate(() => {
119
118
  const isVisible = (el) => {
120
119
  const rect = el.getBoundingClientRect();
121
- return (rect.width > 0 &&
122
- rect.height > 0 &&
123
- getComputedStyle(el).visibility !== 'hidden');
120
+ return rect.width > 0 && rect.height > 0 && getComputedStyle(el).visibility !== 'hidden';
124
121
  };
125
122
  // Match button, link, or ARIA-button variants: AWS renders the
126
123
  // "Allow access" consent action differently across releases
127
124
  // (orange button vs link), so don't assume a <button>.
128
125
  const candidates = Array.from(document.querySelectorAll('button, a, [role="button"], input[type="submit"], input[type="button"]')).filter((el) => isVisible(el));
129
126
  const label = (el) => {
130
- var _a, _b;
131
- return ((_b = (_a = el.value) !== null && _a !== void 0 ? _a : el.textContent) !== null && _b !== void 0 ? _b : '')
132
- .trim()
133
- .toLowerCase();
127
+ var _a;
128
+ const inputValue = el.value;
129
+ // oxlint-disable-next-line typescript/no-unnecessary-condition -- value is undefined on non-inputs
130
+ const text = typeof inputValue === 'string' ? inputValue : ((_a = el.textContent) !== null && _a !== void 0 ? _a : '');
131
+ return text.trim().toLowerCase();
134
132
  };
135
133
  const exact = candidates.find((el) => label(el) === 'allow access');
136
134
  const target = exact !== null && exact !== void 0 ? exact : candidates.find((el) => label(el).includes('allow access'));
@@ -140,17 +138,17 @@ const clickAllowAccessByText = (page) => __awaiter(void 0, void 0, void 0, funct
140
138
  }
141
139
  return false;
142
140
  });
141
+ return clicked;
143
142
  }
144
143
  catch (_a) {
145
- return false;
144
+ return Promise.resolve(false);
146
145
  }
147
- });
146
+ };
148
147
  const dismissAllowAccessPrompt = (page_1, ...args_1) => __awaiter(void 0, [page_1, ...args_1], void 0, function* (page, perSelectorTimeout = 1000) {
149
- for (const selector of exports.allowAccessSelectors) {
150
- if (yield clickSelectorIfPresent(page, selector, perSelectorTimeout)) {
151
- (0, log_1.info)(`click allow-access-button (${selector})`);
152
- return true;
153
- }
148
+ const clicked = yield Promise.all(exports.allowAccessSelectors.map((selector) => clickSelectorIfPresent(page, selector, perSelectorTimeout)));
149
+ if (clicked.some(Boolean)) {
150
+ (0, log_1.info)('click allow-access-button');
151
+ return true;
154
152
  }
155
153
  if (yield clickAllowAccessByText(page)) {
156
154
  (0, log_1.info)('click allow-access-button (text match "Allow access")');
@@ -159,29 +157,40 @@ const dismissAllowAccessPrompt = (page_1, ...args_1) => __awaiter(void 0, [page_
159
157
  return false;
160
158
  });
161
159
  exports.dismissAllowAccessPrompt = dismissAllowAccessPrompt;
160
+ const pollDelayMs = 500;
161
+ const sleepUntilDeadline = (deadline) => __awaiter(void 0, void 0, void 0, function* () {
162
+ const remaining = deadline - Date.now();
163
+ if (remaining <= 0) {
164
+ return;
165
+ }
166
+ yield (0, sleep_1.sleep)(Math.min(pollDelayMs, remaining));
167
+ });
162
168
  const allowAccessIfRequested = (page_1, ...args_1) => __awaiter(void 0, [page_1, ...args_1], void 0, function* (page, timeout = config_1.timeoutMs) {
163
169
  const deadline = Date.now() + timeout;
164
170
  // Poll so a slow-rendering consent dialog is not missed, while still
165
171
  // returning quickly when the prompt appears (or never appears).
166
- while (Date.now() < deadline) {
172
+ // oxlint-disable-next-line no-await-in-loop -- polling must stay sequential to match dialog timing
173
+ for (;;) {
174
+ // oxlint-disable-next-line no-await-in-loop -- each poll depends on the current page state
167
175
  if (yield (0, exports.dismissAllowAccessPrompt)(page)) {
168
176
  return true;
169
177
  }
170
- if (Date.now() + 500 >= deadline) {
171
- break;
178
+ if (Date.now() >= deadline) {
179
+ return false;
172
180
  }
173
- yield new Promise((resolve) => setTimeout(resolve, 500));
181
+ // oxlint-disable-next-line no-await-in-loop -- delay must elapse before the next poll
182
+ yield sleepUntilDeadline(deadline);
174
183
  }
175
- return false;
176
184
  });
177
185
  exports.allowAccessIfRequested = allowAccessIfRequested;
178
186
  const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page_1, ...args_1], void 0, function* (page, timeout = config_1.timeoutMs) {
179
- var _a;
180
187
  const deadline = Date.now() + timeout;
181
188
  let lastError;
182
- while (Date.now() < deadline) {
189
+ // oxlint-disable-next-line no-await-in-loop -- success and consent checks are order-dependent
190
+ for (;;) {
183
191
  // Success already visible?
184
192
  try {
193
+ // oxlint-disable-next-line no-await-in-loop -- must check before dismissing prompts
185
194
  const success = yield page.waitForSelector('[data-analytics-alert="success"]', { timeout: 2000 });
186
195
  if (success) {
187
196
  return;
@@ -194,6 +203,7 @@ const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page
194
203
  // This covers the "Allow <user> to access your data? / Allow access"
195
204
  // dialog which otherwise blocks success indefinitely.
196
205
  try {
206
+ // oxlint-disable-next-line no-await-in-loop -- prompt check follows the success check
197
207
  if (yield (0, exports.dismissAllowAccessPrompt)(page)) {
198
208
  (0, log_1.info)('dismissed allow-access prompt while waiting for success');
199
209
  continue;
@@ -204,6 +214,7 @@ const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page
204
214
  }
205
215
  // Also re-check the other intermediate confirmations while polling.
206
216
  try {
217
+ // oxlint-disable-next-line no-await-in-loop -- confirmation check follows the success check
207
218
  if (yield clickSelectorIfPresent(page, '[data-analytics="accept-user-code"]', 1000)) {
208
219
  (0, log_1.info)('click accept-user-code (while waiting for success)');
209
220
  continue;
@@ -213,6 +224,7 @@ const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page
213
224
  (0, log_1.debug)('error clicking accept-user-code while waiting:', e);
214
225
  }
215
226
  try {
227
+ // oxlint-disable-next-line no-await-in-loop -- auth request check follows the success check
216
228
  if (yield clickSelectorIfPresent(page, '#cli_verification_btn', 1000)) {
217
229
  (0, log_1.info)('clicking auth request button (while waiting for success)');
218
230
  }
@@ -220,6 +232,11 @@ const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page
220
232
  catch (e) {
221
233
  (0, log_1.debug)('error clicking auth request button while waiting:', e);
222
234
  }
235
+ if (Date.now() >= deadline) {
236
+ break;
237
+ }
238
+ // oxlint-disable-next-line no-await-in-loop -- delay must elapse before the next poll
239
+ yield sleepUntilDeadline(deadline);
223
240
  }
224
241
  // Final wait to surface a clear TimeoutError if success never arrived.
225
242
  try {
@@ -227,8 +244,11 @@ const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page
227
244
  timeout: config_1.timeoutShortMs,
228
245
  });
229
246
  }
230
- catch (_b) {
231
- throw ((_a = lastError) !== null && _a !== void 0 ? _a : new Error('Timed out waiting for success'));
247
+ catch (_a) {
248
+ if (lastError instanceof Error) {
249
+ throw lastError;
250
+ }
251
+ throw new Error('Timed out waiting for success');
232
252
  }
233
253
  });
234
254
  function getMFA(p) {
package/package.json CHANGED
@@ -1,12 +1,10 @@
1
1
  {
2
2
  "name": "ag-awsauth",
3
+ "version": "0.0.294",
4
+ "private": false,
3
5
  "description": "auth to aws sso/iamv2 easily",
4
- "main": "dist/index.js",
5
- "author": "andreigec@hotmail.com",
6
6
  "license": "ISC",
7
- "private": false,
8
- "version": "0.0.293",
9
- "preferGlobal": true,
7
+ "author": "andreigec@hotmail.com",
10
8
  "bin": {
11
9
  "ag-awsauth": "./bin/awsauth.js"
12
10
  },
@@ -16,18 +14,21 @@
16
14
  "README.md",
17
15
  "LICENSE.md"
18
16
  ],
17
+ "main": "dist/index.js",
19
18
  "dependencies": {
20
19
  "@aws-sdk/client-sso": "3.972.0",
21
20
  "@aws-sdk/client-sso-oidc": "3.972.0",
22
21
  "@aws-sdk/client-sts": "3.972.0",
23
22
  "@aws-sdk/shared-ini-file-loader": "3.374.0",
24
- "ag-common": "0.0.861",
23
+ "ag-common": "0.0.911",
25
24
  "cli-select": "1.1.2",
26
25
  "dotenv": "17.2.3",
27
26
  "envfile": "7.1.0",
28
- "eslint-config-e7npm": "0.1.31",
27
+ "eslint-config-e7npm": "0.1.68",
29
28
  "ini": "5.0.0",
30
29
  "node-fetch": "3.3.2",
30
+ "oxfmt": "^0.65.0",
31
+ "oxlint": "^1.83.0",
31
32
  "puppeteer": "24.35.0",
32
33
  "readline-sync": "1.4.10",
33
34
  "typescript": "5.9.3",
@@ -43,12 +44,14 @@
43
44
  "resolutions": {
44
45
  "ws": ">=8.17.1"
45
46
  },
47
+ "preferGlobal": true,
46
48
  "engines": {
47
49
  "node": ">=20"
48
50
  },
49
51
  "scripts": {
50
- "lint": "eslint src",
51
- "format": "eslint src --fix",
52
+ "format": "e7-oxfmt --config .oxfmtrc.json --disable-nested-config .",
53
+ "lint": "e7-oxlint --config .oxlintrc.json --deny-warnings src && pnpm run typecheck",
54
+ "typecheck": "tsc --noEmit",
52
55
  "test": "tsc && node --test test/*.test.js",
53
56
  "start": "tsc && node bin/awsauth.js",
54
57
  "build": "tsc"