@deque/axe-auth 1.1.0-next.721c7626 → 1.1.0-next.7469dec9

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.
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.refreshTokens = refreshTokens;
4
4
  const errors_1 = require("./errors");
5
+ const retry_1 = require("./retry");
5
6
  const tokenResponse_1 = require("./tokenResponse");
6
7
  const userAgent_1 = require("../userAgent");
7
8
  /**
@@ -31,11 +32,11 @@ async function refreshTokens(options) {
31
32
  grant_type: "refresh_token",
32
33
  client_id: options.clientId,
33
34
  refresh_token: options.refreshToken,
34
- });
35
+ }).toString();
35
36
  const issuedAt = now();
36
37
  let response;
37
38
  try {
38
- response = await fetch(options.tokenEndpoint, {
39
+ response = await (0, retry_1.fetchWithRetry)(options.tokenEndpoint, {
39
40
  method: "POST",
40
41
  headers: {
41
42
  "Content-Type": "application/x-www-form-urlencoded",
@@ -0,0 +1 @@
1
+ export declare function fetchWithRetry(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ // undici's `RetryAgent` cannot retry POSTs through `fetch()` — its retry
3
+ // handler aborts once the fetch ReadableStream body is consumed. Re-invoking
4
+ // `fetch()` per attempt with a string body sidesteps that. POST replay is
5
+ // safe for our OAuth endpoints by spec: single-use codes (RFC 6749 §4.1.2),
6
+ // refresh requests that never reached the server (§6), no-op revocation
7
+ // (RFC 7009 §2.2).
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.fetchWithRetry = fetchWithRetry;
10
+ const promises_1 = require("node:timers/promises");
11
+ const MAX_RETRIES = 3;
12
+ const CONNECTION_ERROR_CODES = new Set([
13
+ "ECONNRESET",
14
+ "ECONNREFUSED",
15
+ "ENOTFOUND",
16
+ "ENETDOWN",
17
+ "ENETUNREACH",
18
+ "EHOSTDOWN",
19
+ "UND_ERR_SOCKET",
20
+ ]);
21
+ function isConnectionError(err) {
22
+ const seen = new Set();
23
+ let current = err;
24
+ while (current && typeof current === "object" && !seen.has(current)) {
25
+ seen.add(current);
26
+ const e = current;
27
+ if (typeof e.code === "string" && CONNECTION_ERROR_CODES.has(e.code)) {
28
+ return true;
29
+ }
30
+ current = e.cause;
31
+ }
32
+ return false;
33
+ }
34
+ async function fetchWithRetry(input, init) {
35
+ for (let attempt = 0;; attempt++) {
36
+ try {
37
+ return await fetch(input, init);
38
+ }
39
+ catch (err) {
40
+ if (attempt >= MAX_RETRIES || !isConnectionError(err)) {
41
+ throw err;
42
+ }
43
+ // Exponential backoff: 500ms, 1s, 2s, capped at 30s.
44
+ // `sleep` honors `init.signal` so an aborted request interrupts the wait.
45
+ const delay = Math.min(500 * Math.pow(2, attempt), 30_000);
46
+ await (0, promises_1.setTimeout)(delay, undefined, { signal: init?.signal ?? undefined });
47
+ }
48
+ }
49
+ }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.revokeRefreshToken = revokeRefreshToken;
4
+ const retry_1 = require("./retry");
4
5
  const userAgent_1 = require("../userAgent");
5
6
  /**
6
7
  * Revokes a refresh token via RFC 7009. Servers SHOULD return 200
@@ -23,10 +24,10 @@ async function revokeRefreshToken(options) {
23
24
  token: options.refreshToken,
24
25
  token_type_hint: "refresh_token",
25
26
  client_id: options.clientId,
26
- });
27
+ }).toString();
27
28
  let response;
28
29
  try {
29
- response = await fetch(options.revocationEndpoint, {
30
+ response = await (0, retry_1.fetchWithRetry)(options.revocationEndpoint, {
30
31
  method: "POST",
31
32
  headers: {
32
33
  "Content-Type": "application/x-www-form-urlencoded",
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.exchangeCodeForTokens = exchangeCodeForTokens;
4
4
  const errors_1 = require("./errors");
5
+ const retry_1 = require("./retry");
5
6
  const tokenResponse_1 = require("./tokenResponse");
6
7
  const userAgent_1 = require("../userAgent");
7
8
  /**
@@ -19,11 +20,11 @@ async function exchangeCodeForTokens(options) {
19
20
  code: options.code,
20
21
  code_verifier: options.codeVerifier,
21
22
  redirect_uri: options.redirectUri,
22
- });
23
+ }).toString();
23
24
  const issuedAt = now();
24
25
  let response;
25
26
  try {
26
- response = await fetch(options.tokenEndpoint, {
27
+ response = await (0, retry_1.fetchWithRetry)(options.tokenEndpoint, {
27
28
  method: "POST",
28
29
  headers: {
29
30
  "Content-Type": "application/x-www-form-urlencoded",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deque/axe-auth",
3
- "version": "1.1.0-next.721c7626",
3
+ "version": "1.1.0-next.7469dec9",
4
4
  "description": "CLI authentication utility for Deque services",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {