lifecycleion 0.0.19 → 0.0.21

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.
Files changed (74) hide show
  1. package/README.md +39 -36
  2. package/dist/lib/event-emitter.cjs +195 -9
  3. package/dist/lib/event-emitter.cjs.map +1 -1
  4. package/dist/lib/event-emitter.js +195 -9
  5. package/dist/lib/event-emitter.js.map +1 -1
  6. package/dist/lib/global-event-target.cjs +217 -0
  7. package/dist/lib/global-event-target.cjs.map +1 -0
  8. package/dist/lib/global-event-target.d.cts +70 -0
  9. package/dist/lib/global-event-target.d.ts +70 -0
  10. package/dist/lib/global-event-target.js +189 -0
  11. package/dist/lib/global-event-target.js.map +1 -0
  12. package/dist/lib/http-client/index.cjs +554 -193
  13. package/dist/lib/http-client/index.cjs.map +1 -1
  14. package/dist/lib/http-client/index.d.cts +9 -3
  15. package/dist/lib/http-client/index.d.ts +9 -3
  16. package/dist/lib/http-client/index.js +554 -193
  17. package/dist/lib/http-client/index.js.map +1 -1
  18. package/dist/lib/http-client-mock/index.cjs +71 -24
  19. package/dist/lib/http-client-mock/index.cjs.map +1 -1
  20. package/dist/lib/http-client-mock/index.d.cts +50 -2
  21. package/dist/lib/http-client-mock/index.d.ts +50 -2
  22. package/dist/lib/http-client-mock/index.js +71 -24
  23. package/dist/lib/http-client-mock/index.js.map +1 -1
  24. package/dist/lib/http-client-node/index.cjs +135 -33
  25. package/dist/lib/http-client-node/index.cjs.map +1 -1
  26. package/dist/lib/http-client-node/index.d.cts +33 -2
  27. package/dist/lib/http-client-node/index.d.ts +33 -2
  28. package/dist/lib/http-client-node/index.js +135 -33
  29. package/dist/lib/http-client-node/index.js.map +1 -1
  30. package/dist/lib/http-client-xhr/index.cjs +0 -14
  31. package/dist/lib/http-client-xhr/index.cjs.map +1 -1
  32. package/dist/lib/http-client-xhr/index.d.cts +3 -2
  33. package/dist/lib/http-client-xhr/index.d.ts +3 -2
  34. package/dist/lib/http-client-xhr/index.js +0 -14
  35. package/dist/lib/http-client-xhr/index.js.map +1 -1
  36. package/dist/lib/lifecycle-manager/index.cjs +199 -13
  37. package/dist/lib/lifecycle-manager/index.cjs.map +1 -1
  38. package/dist/lib/lifecycle-manager/index.js +199 -13
  39. package/dist/lib/lifecycle-manager/index.js.map +1 -1
  40. package/dist/lib/logger/index.cjs +203 -21
  41. package/dist/lib/logger/index.cjs.map +1 -1
  42. package/dist/lib/logger/index.d.cts +5 -1
  43. package/dist/lib/logger/index.d.ts +5 -1
  44. package/dist/lib/logger/index.js +203 -21
  45. package/dist/lib/logger/index.js.map +1 -1
  46. package/dist/lib/lru-cache/index.cjs +195 -9
  47. package/dist/lib/lru-cache/index.cjs.map +1 -1
  48. package/dist/lib/lru-cache/index.js +195 -9
  49. package/dist/lib/lru-cache/index.js.map +1 -1
  50. package/dist/lib/process-signal-manager.cjs +199 -13
  51. package/dist/lib/process-signal-manager.cjs.map +1 -1
  52. package/dist/lib/process-signal-manager.js +199 -13
  53. package/dist/lib/process-signal-manager.js.map +1 -1
  54. package/dist/lib/promise-protected-resolver.cjs +195 -9
  55. package/dist/lib/promise-protected-resolver.cjs.map +1 -1
  56. package/dist/lib/promise-protected-resolver.js +195 -9
  57. package/dist/lib/promise-protected-resolver.js.map +1 -1
  58. package/dist/lib/retry-utils/index.cjs +195 -9
  59. package/dist/lib/retry-utils/index.cjs.map +1 -1
  60. package/dist/lib/retry-utils/index.js +195 -9
  61. package/dist/lib/retry-utils/index.js.map +1 -1
  62. package/dist/lib/safe-handle-callback.cjs +196 -18
  63. package/dist/lib/safe-handle-callback.cjs.map +1 -1
  64. package/dist/lib/safe-handle-callback.d.cts +14 -4
  65. package/dist/lib/safe-handle-callback.d.ts +14 -4
  66. package/dist/lib/safe-handle-callback.js +196 -18
  67. package/dist/lib/safe-handle-callback.js.map +1 -1
  68. package/dist/lib/single-event-observer.cjs +195 -9
  69. package/dist/lib/single-event-observer.cjs.map +1 -1
  70. package/dist/lib/single-event-observer.js +195 -9
  71. package/dist/lib/single-event-observer.js.map +1 -1
  72. package/dist/{types-CWw885iO.d.cts → types-BFvpJPMt.d.cts} +72 -11
  73. package/dist/{types-Mso0dYOS.d.ts → types-BONtIhQ5.d.ts} +72 -11
  74. package/package.json +31 -12
@@ -246,12 +246,30 @@ interface AdapterResponse {
246
246
  */
247
247
  isTransportError?: boolean;
248
248
  /**
249
- * Set to `false` when the adapter knows the request/response progressed far
250
- * enough that replay is unsafe, even if `status` would normally be retried
251
- * by the client (for example a mid-upload socket write failure after some
252
- * bytes may already have left the process).
249
+ * Set to `false` when no attempt can succeed, whatever the method a rejected
250
+ * TLS certificate, say. Honoured for every method, and it overrides
251
+ * `retryNonIdempotentMethods`.
252
+ *
253
+ * Do **not** set it for a failure that merely might have been delivered, such
254
+ * as one that struck mid-upload: that vetoes retries for methods where replay
255
+ * is safe by definition. Report
256
+ * {@link AdapterResponse.wasDefinitelyNotSent} instead, or report nothing.
257
+ *
258
+ * Only `false` carries meaning. `true` is a hint, and never authorizes
259
+ * replaying a non-idempotent request.
253
260
  */
254
261
  isRetryable?: boolean;
262
+ /**
263
+ * Set to `true` only when the adapter can prove no request bytes reached the
264
+ * server — a refused connection, a name that did not resolve. Absence means
265
+ * "not known", never "known to be safe".
266
+ *
267
+ * Deliberately separate from {@link AdapterResponse.isRetryable}, which is a
268
+ * hint that says nothing about delivery. The client uses this to decide whether
269
+ * a `POST` or `PATCH` may be retried after a transport failure, and ignores it
270
+ * when a real response came back.
271
+ */
272
+ wasDefinitelyNotSent?: boolean;
255
273
  /**
256
274
  * Final request headers actually used by the adapter after adapter-local
257
275
  * mutations (for example multipart Content-Type/Content-Length added by the
@@ -276,12 +294,19 @@ interface AdapterResponse {
276
294
  */
277
295
  isStreamed?: boolean;
278
296
  /**
279
- * Set by NodeAdapter when response-body delivery fails after headers arrive
280
- * (for example buffered-download truncation, writable errors, or upstream
281
- * response-stream errors). The client treats this as a terminal stream
282
- * failure: isStreamError: true. The real HTTP status is preserved (not
283
- * zeroed) so observers can tell the server responded but body delivery still
284
- * failed locally/in-flight.
297
+ * Set when response-body delivery fails after headers arrive — buffered
298
+ * download truncation, writable errors, upstream response-stream errors.
299
+ * NodeAdapter, FetchAdapter and MockAdapter all report it, and the client
300
+ * synthesizes it for a per-attempt timeout that strikes mid-body. XHRAdapter
301
+ * cannot: `XMLHttpRequest` zeroes the status on error.
302
+ *
303
+ * The client treats this as a terminal stream failure. The real HTTP status is
304
+ * preserved (not zeroed) so observers can tell the server responded but body
305
+ * delivery still failed.
306
+ *
307
+ * For replay decisions this groups with a real response, **not** with a
308
+ * transport failure: headers arrived, so the server processed the request and
309
+ * may have committed it, the same thing a 500 tells you.
285
310
  */
286
311
  isStreamError?: boolean;
287
312
  /**
@@ -395,6 +420,23 @@ interface AttemptEndEvent {
395
420
  attemptNumber: number;
396
421
  isRetry: boolean;
397
422
  willRetry: boolean;
423
+ /**
424
+ * Why no retry happened, when a retry was genuinely available to suppress — a
425
+ * policy is configured, it has attempts left, and the status alone would have
426
+ * allowed one. Absent otherwise, since nothing was suppressed.
427
+ *
428
+ * - `adapter_veto` — the adapter reported `isRetryable: false`. Not produced by
429
+ * a real transport, which pairs that flag with the non-retryable `495`;
430
+ * reachable from `MockAdapter` and custom adapters.
431
+ * - `stream_error` — the body failed after headers arrived, so the server
432
+ * received the request and the outcome is unknown.
433
+ * - `non_idempotent_method` — a `POST` or `PATCH` with no proof the request
434
+ * went undelivered. Set `retryNonIdempotentMethods` to allow it.
435
+ *
436
+ * Exists so a suppressed retry is self-explaining: `willRetry: false` alone is
437
+ * indistinguishable from a policy declining.
438
+ */
439
+ retrySuppressedReason?: 'adapter_veto' | 'stream_error' | 'non_idempotent_method';
398
440
  /** Present only when a retry has been scheduled after this attempt. */
399
441
  nextRetryDelayMS?: number;
400
442
  /** Epoch ms for the scheduled retry, when a retry has been scheduled. */
@@ -423,6 +465,20 @@ interface HTTPClientConfig {
423
465
  timeout?: number;
424
466
  cookieJar?: CookieJar | null;
425
467
  retryPolicy?: RetryPolicyOptions;
468
+ /**
469
+ * Whether a retry policy may replay `POST` and `PATCH`, the methods RFC 9110
470
+ * does not define as idempotent. Defaults to `false`.
471
+ *
472
+ * When `false`, such a request is never retried after a real HTTP response —
473
+ * a 500 still means the handler ran and may have committed — and after a
474
+ * transport failure only when the adapter reports
475
+ * {@link AdapterResponse.wasDefinitelyNotSent}. A bare transport failure is not
476
+ * enough, and neither is `isRetryable: true`.
477
+ *
478
+ * Set to `true` when writes are guarded by an idempotency key or are naturally
479
+ * safe to repeat. Idempotent methods are unaffected either way.
480
+ */
481
+ retryNonIdempotentMethods?: boolean;
426
482
  includeRequestID?: boolean;
427
483
  includeAttemptHeader?: boolean;
428
484
  userAgent?: string;
@@ -448,6 +504,11 @@ interface HTTPRequestOptions {
448
504
  timeout?: number;
449
505
  signal?: AbortSignal;
450
506
  retryPolicy?: RetryPolicyOptions | null;
507
+ /**
508
+ * Per-request override for {@link HTTPClientConfig.retryNonIdempotentMethods}.
509
+ * Falls back to the client config when omitted.
510
+ */
511
+ retryNonIdempotentMethods?: boolean;
451
512
  label?: string;
452
513
  onUploadProgress?: (event: HTTPProgressEvent) => void;
453
514
  onDownloadProgress?: (event: HTTPProgressEvent) => void;
@@ -865,4 +926,4 @@ type ResponseObserver = (response: HTTPResponse, request: AttemptRequest, phase:
865
926
  type ErrorObserver = (error: HTTPClientError, request: AttemptRequest, phase: ErrorObserverPhase) => void | Promise<void>;
866
927
  type RequestState = 'pending' | 'sending' | 'waiting_for_retry' | 'completed' | 'cancelled' | 'failed';
867
928
 
868
- export { type AdapterType as A, type InterceptorPhaseName as B, type ContentType as C, type QueryValue as D, type ErrorObserver as E, type RedirectHopInfo as F, type RequestInterceptorContext as G, type HTTPAdapter as H, type InterceptedRequest as I, type RequestPhase as J, type RequestPhaseName as K, type ResponseObserverPhase as L, type ResponseObserverPhaseName as M, type StreamResponseCancel as N, type StreamResponseContext as O, type StreamResponseInfo as P, type QueryObject as Q, type RequestState as R, type StreamResponseFactory as S, type WritableLike as W, type AdapterRequest as a, type AdapterResponse as b, type HTTPMethod as c, type HTTPRequestOptions as d, type HTTPResponse as e, type HTTPClientError as f, type HTTPProgressEvent as g, type AttemptStartEvent as h, type AttemptEndEvent as i, type HTTPClientConfig as j, type RequestInterceptor as k, type RequestInterceptorFilter as l, type ResponseObserver as m, type ResponseObserverFilter as n, type ErrorObserverFilter as o, type SubClientConfig as p, type AttemptRequest as q, type Cookie as r, type CookieInput as s, CookieJar as t, type CookieJarJSON as u, type ErrorCode as v, type ErrorObserverPhase as w, type ErrorObserverPhaseName as x, type InterceptorCancel as y, type InterceptorPhase as z };
929
+ export { type AdapterType as A, type ErrorObserverPhase as B, type ContentType as C, type ErrorObserverPhaseName as D, type ErrorObserver as E, type InterceptorCancel as F, type InterceptorPhase as G, type HTTPAdapter as H, type InterceptedRequest as I, type InterceptorPhaseName as J, type QueryValue as K, type RedirectHopInfo as L, type RequestInterceptorContext as M, type RequestPhase as N, type RequestPhaseName as O, type ResponseObserverPhase as P, type QueryObject as Q, type RequestState as R, type StreamResponseCancel as S, type ResponseObserverPhaseName as T, type WritableLike as W, type AdapterRequest as a, type AdapterResponse as b, type AdapterProgressEvent as c, type HTTPMethod as d, type StreamResponseContext as e, type StreamResponseFactory as f, type StreamResponseInfo as g, type HTTPRequestOptions as h, type HTTPResponse as i, type HTTPClientError as j, type HTTPProgressEvent as k, type AttemptStartEvent as l, type AttemptEndEvent as m, type HTTPClientConfig as n, type RequestInterceptor as o, type RequestInterceptorFilter as p, type ResponseObserver as q, type ResponseObserverFilter as r, type ErrorObserverFilter as s, type SubClientConfig as t, type AttemptRequest as u, type Cookie as v, type CookieInput as w, CookieJar as x, type CookieJarJSON as y, type ErrorCode as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lifecycleion",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
4
4
  "type": "module",
5
5
  "description": "A collection of foundational TypeScript utilities for managing application lifecycle, logging, retries, events, and common programming patterns",
6
6
  "exports": {
@@ -54,6 +54,11 @@
54
54
  "import": "./dist/lib/error-to-string.js",
55
55
  "require": "./dist/lib/error-to-string.cjs"
56
56
  },
57
+ "./global-event-target": {
58
+ "types": "./dist/lib/global-event-target.d.ts",
59
+ "import": "./dist/lib/global-event-target.js",
60
+ "require": "./dist/lib/global-event-target.cjs"
61
+ },
57
62
  "./event-emitter": {
58
63
  "types": "./dist/lib/event-emitter.d.ts",
59
64
  "import": "./dist/lib/event-emitter.js",
@@ -185,6 +190,15 @@
185
190
  "require": "./dist/lib/http-client-mock/index.cjs"
186
191
  }
187
192
  },
193
+ "main": "./dist/index.cjs",
194
+ "module": "./dist/index.js",
195
+ "types": "./dist/index.d.ts",
196
+ "sideEffects": [
197
+ "./dist/lib/safe-handle-callback.js",
198
+ "./dist/lib/safe-handle-callback.cjs",
199
+ "./dist/lib/logger/index.js",
200
+ "./dist/lib/logger/index.cjs"
201
+ ],
188
202
  "files": [
189
203
  "dist"
190
204
  ],
@@ -226,21 +240,26 @@
226
240
  "license": "MIT",
227
241
  "repository": {
228
242
  "type": "git",
229
- "url": "https://github.com/keverw/lifecycleion"
243
+ "url": "git+https://github.com/keverw/lifecycleion.git"
244
+ },
245
+ "homepage": "https://github.com/keverw/lifecycleion#readme",
246
+ "bugs": {
247
+ "url": "https://github.com/keverw/lifecycleion/issues"
230
248
  },
231
249
  "overrides": {
232
- "brace-expansion": "5.0.8",
233
- "esbuild": "0.28.1"
250
+ "brace-expansion": "5.0.9",
251
+ "esbuild": "0.28.1",
252
+ "js-yaml": "4.3.1"
234
253
  },
235
254
  "devDependencies": {
236
255
  "@eslint/js": "^9.39.5",
237
- "@playwright/test": "^1.62.0",
238
- "@types/bun": "^1.3.14",
256
+ "@playwright/test": "^1.62.1",
257
+ "@types/bun": "1.3.14",
239
258
  "@types/node": "^24.13.3",
240
259
  "@types/qs": "^6.15.1",
241
260
  "@types/tr46": "^5.0.1",
242
- "@typescript-eslint/eslint-plugin": "^8.65.0",
243
- "@typescript-eslint/parser": "^8.65.0",
261
+ "@typescript-eslint/eslint-plugin": "^8.67.0",
262
+ "@typescript-eslint/parser": "^8.67.0",
244
263
  "eslint": "^9.39.5",
245
264
  "eslint-import-resolver-typescript": "^4.4.5",
246
265
  "eslint-plugin-check-file": "^3.3.2",
@@ -253,19 +272,19 @@
253
272
  "prettier": "^3.9.6",
254
273
  "tsup": "^8.5.1",
255
274
  "typescript": "^5.9.3",
256
- "typescript-eslint": "^8.65.0"
275
+ "typescript-eslint": "^8.67.0"
257
276
  },
258
277
  "dependencies": {
259
278
  "bson-objectid": "^2.0.4",
260
279
  "chalk": "^5.6.2",
261
280
  "datamask": "^1.0.0",
262
281
  "date-fns": "^4.4.0",
263
- "find-my-way": "^9.7.0",
282
+ "find-my-way": "^9.8.0",
264
283
  "qs": "^6.15.3",
265
284
  "string-width": "^8.2.2",
266
- "tldts": "^7.4.9",
285
+ "tldts": "^7.4.10",
267
286
  "tr46": "^6.0.0",
268
287
  "ulid": "^3.0.2",
269
- "uuid": "^14.0.1"
288
+ "uuid": "^14.0.2"
270
289
  }
271
290
  }