@sdxc/activitypub 2026.10.24 → 2026.10.26

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.
@@ -98,11 +98,11 @@ export interface Delivered {
98
98
  */
99
99
  export declare function deliver(input: DeliveryInput, options: DeliverOptions): Promise<Result<Delivered, DeliveryError>>;
100
100
  /**
101
- * Reads `Retry-After` as milliseconds from `now`: delay-seconds or an HTTP date, clamped to
102
- * `0` through `MAX_RETRY_AFTER_MS`, so an inbox can postpone a retry no longer than the
103
- * longest backoff step. Anything else reads as `null`.
101
+ * Reads `Retry-After` as milliseconds from `now`, capped at `MAX_RETRY_AFTER_MS` so an inbox
102
+ * can postpone a retry no longer than the longest backoff step. A header naming no usable
103
+ * delay reads as `null`, leaving the wait to the backoff.
104
104
  *
105
105
  * @param value - The header value.
106
106
  * @param now - The time the answer arrived.
107
107
  */
108
- export declare function parseRetryAfter(value: string | null, now: Date): number | null;
108
+ export declare function retryAfterWait(value: string | null, now: Date): number | null;
@@ -1,6 +1,7 @@
1
1
  import { createBackoff } from "@sdxc/backoff";
2
2
  import { toMs } from "@sdxc/duration";
3
3
  import { parseAcceptSignature, sign } from "@sdxc/http-signatures";
4
+ import { parseRetryAfter } from "@sdxc/http/retry-after";
4
5
  import { checkUrl, release, resolveHost } from "@sdxc/outbound";
5
6
  import { failure, isFailure, isSuccess, success } from "@sdxc/result";
6
7
  import { ActivityPubError } from "../errors.js";
@@ -288,31 +289,26 @@ function errorFor(inbox, response, now) {
288
289
  if (status === 429) {
289
290
  return new DeliveryError("rate-limited", inbox, `${inbox} is rate limiting`, {
290
291
  status,
291
- retryAfter: parseRetryAfter(response.headers.get("retry-after"), now),
292
+ retryAfter: retryAfterWait(response.headers.get("retry-after"), now),
292
293
  });
293
294
  }
294
295
  if (status >= 500) {
295
296
  return new DeliveryError("server", inbox, `${inbox} answered ${status}`, {
296
297
  status,
297
- retryAfter: parseRetryAfter(response.headers.get("retry-after"), now),
298
+ retryAfter: retryAfterWait(response.headers.get("retry-after"), now),
298
299
  });
299
300
  }
300
301
  return new DeliveryError("rejected", inbox, `${inbox} rejected the activity with ${status}`, options);
301
302
  }
302
303
  /**
303
- * Reads `Retry-After` as milliseconds from `now`: delay-seconds or an HTTP date, clamped to
304
- * `0` through `MAX_RETRY_AFTER_MS`, so an inbox can postpone a retry no longer than the
305
- * longest backoff step. Anything else reads as `null`.
304
+ * Reads `Retry-After` as milliseconds from `now`, capped at `MAX_RETRY_AFTER_MS` so an inbox
305
+ * can postpone a retry no longer than the longest backoff step. A header naming no usable
306
+ * delay reads as `null`, leaving the wait to the backoff.
306
307
  *
307
308
  * @param value - The header value.
308
309
  * @param now - The time the answer arrived.
309
310
  */
310
- export function parseRetryAfter(value, now) {
311
- if (value === null)
312
- return null;
313
- let text = value.trim();
314
- let delay = /^-?\d+$/u.test(text) ? Number(text) * 1000 : Date.parse(text) - now.getTime();
315
- if (Number.isNaN(delay))
316
- return null;
317
- return Math.min(MAX_RETRY_AFTER_MS, Math.max(0, delay));
311
+ export function retryAfterWait(value, now) {
312
+ let wait = parseRetryAfter(value, now);
313
+ return wait === null ? null : Math.min(MAX_RETRY_AFTER_MS, wait);
318
314
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdxc/activitypub",
3
- "version": "2026.10.24",
3
+ "version": "2026.10.26",
4
4
  "description": "ActivityPub protocol logic: vocabulary, actors, discovery, a verified inbox and signed delivery",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -14,14 +14,14 @@
14
14
  "@sdxc/crypto": "2026.10.23",
15
15
  "@sdxc/duration": "2026.10.13",
16
16
  "@sdxc/html": "2026.10.24",
17
- "@sdxc/http": "2026.10.24",
18
- "@sdxc/http-signatures": "2026.10.24",
17
+ "@sdxc/http": "2026.10.26",
18
+ "@sdxc/http-signatures": "2026.10.26",
19
19
  "@sdxc/json-pointer": "2026.10.14",
20
20
  "@sdxc/logger": "2026.10.24",
21
- "@sdxc/outbound": "2026.10.24",
21
+ "@sdxc/outbound": "2026.10.25",
22
22
  "@sdxc/result": "2026.10.13",
23
23
  "@sdxc/uuid": "2026.10.13",
24
- "@sdxc/well-known": "2026.10.24"
24
+ "@sdxc/well-known": "2026.10.26"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "remix": "3.1.0",
@@ -32,7 +32,7 @@
32
32
  "optional": true
33
33
  }
34
34
  },
35
- "gitHead": "f9db0f8f1f51a256e74b94b0f4b1db4be9880370",
35
+ "gitHead": "ff18988bd00de6200766dbc77367257277979566",
36
36
  "publishConfig": {
37
37
  "access": "public"
38
38
  },