lifecycleion 0.0.1

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 (177) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +125 -0
  3. package/dist/index.cjs +7 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +2 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +5 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/lib/arrays.cjs +95 -0
  10. package/dist/lib/arrays.cjs.map +1 -0
  11. package/dist/lib/arrays.d.cts +15 -0
  12. package/dist/lib/arrays.d.ts +15 -0
  13. package/dist/lib/arrays.js +63 -0
  14. package/dist/lib/arrays.js.map +1 -0
  15. package/dist/lib/ascii-tables/index.cjs +642 -0
  16. package/dist/lib/ascii-tables/index.cjs.map +1 -0
  17. package/dist/lib/ascii-tables/index.d.cts +66 -0
  18. package/dist/lib/ascii-tables/index.d.ts +66 -0
  19. package/dist/lib/ascii-tables/index.js +603 -0
  20. package/dist/lib/ascii-tables/index.js.map +1 -0
  21. package/dist/lib/clamp.cjs +41 -0
  22. package/dist/lib/clamp.cjs.map +1 -0
  23. package/dist/lib/clamp.d.cts +26 -0
  24. package/dist/lib/clamp.d.ts +26 -0
  25. package/dist/lib/clamp.js +15 -0
  26. package/dist/lib/clamp.js.map +1 -0
  27. package/dist/lib/constants.cjs +73 -0
  28. package/dist/lib/constants.cjs.map +1 -0
  29. package/dist/lib/constants.d.cts +17 -0
  30. package/dist/lib/constants.d.ts +17 -0
  31. package/dist/lib/constants.js +34 -0
  32. package/dist/lib/constants.js.map +1 -0
  33. package/dist/lib/curly-brackets.cjs +77 -0
  34. package/dist/lib/curly-brackets.cjs.map +1 -0
  35. package/dist/lib/curly-brackets.d.cts +17 -0
  36. package/dist/lib/curly-brackets.d.ts +17 -0
  37. package/dist/lib/curly-brackets.js +52 -0
  38. package/dist/lib/curly-brackets.js.map +1 -0
  39. package/dist/lib/deep-clone.cjs +87 -0
  40. package/dist/lib/deep-clone.cjs.map +1 -0
  41. package/dist/lib/deep-clone.d.cts +19 -0
  42. package/dist/lib/deep-clone.d.ts +19 -0
  43. package/dist/lib/deep-clone.js +62 -0
  44. package/dist/lib/deep-clone.js.map +1 -0
  45. package/dist/lib/error-to-string.cjs +743 -0
  46. package/dist/lib/error-to-string.cjs.map +1 -0
  47. package/dist/lib/error-to-string.d.cts +3 -0
  48. package/dist/lib/error-to-string.d.ts +3 -0
  49. package/dist/lib/error-to-string.js +706 -0
  50. package/dist/lib/error-to-string.js.map +1 -0
  51. package/dist/lib/event-emitter.cjs +899 -0
  52. package/dist/lib/event-emitter.cjs.map +1 -0
  53. package/dist/lib/event-emitter.d.cts +78 -0
  54. package/dist/lib/event-emitter.d.ts +78 -0
  55. package/dist/lib/event-emitter.js +861 -0
  56. package/dist/lib/event-emitter.js.map +1 -0
  57. package/dist/lib/id-helpers.cjs +205 -0
  58. package/dist/lib/id-helpers.cjs.map +1 -0
  59. package/dist/lib/id-helpers.d.cts +198 -0
  60. package/dist/lib/id-helpers.d.ts +198 -0
  61. package/dist/lib/id-helpers.js +170 -0
  62. package/dist/lib/id-helpers.js.map +1 -0
  63. package/dist/lib/is-boolean.cjs +33 -0
  64. package/dist/lib/is-boolean.cjs.map +1 -0
  65. package/dist/lib/is-boolean.d.cts +19 -0
  66. package/dist/lib/is-boolean.d.ts +19 -0
  67. package/dist/lib/is-boolean.js +8 -0
  68. package/dist/lib/is-boolean.js.map +1 -0
  69. package/dist/lib/is-function.cjs +33 -0
  70. package/dist/lib/is-function.cjs.map +1 -0
  71. package/dist/lib/is-function.d.cts +3 -0
  72. package/dist/lib/is-function.d.ts +3 -0
  73. package/dist/lib/is-function.js +8 -0
  74. package/dist/lib/is-function.js.map +1 -0
  75. package/dist/lib/is-number.cjs +38 -0
  76. package/dist/lib/is-number.cjs.map +1 -0
  77. package/dist/lib/is-number.d.cts +38 -0
  78. package/dist/lib/is-number.d.ts +38 -0
  79. package/dist/lib/is-number.js +12 -0
  80. package/dist/lib/is-number.js.map +1 -0
  81. package/dist/lib/is-plain-object.cjs +33 -0
  82. package/dist/lib/is-plain-object.cjs.map +1 -0
  83. package/dist/lib/is-plain-object.d.cts +20 -0
  84. package/dist/lib/is-plain-object.d.ts +20 -0
  85. package/dist/lib/is-plain-object.js +8 -0
  86. package/dist/lib/is-plain-object.js.map +1 -0
  87. package/dist/lib/is-promise.cjs +34 -0
  88. package/dist/lib/is-promise.cjs.map +1 -0
  89. package/dist/lib/is-promise.d.cts +3 -0
  90. package/dist/lib/is-promise.d.ts +3 -0
  91. package/dist/lib/is-promise.js +9 -0
  92. package/dist/lib/is-promise.js.map +1 -0
  93. package/dist/lib/json-helpers.cjs +49 -0
  94. package/dist/lib/json-helpers.cjs.map +1 -0
  95. package/dist/lib/json-helpers.d.cts +10 -0
  96. package/dist/lib/json-helpers.d.ts +10 -0
  97. package/dist/lib/json-helpers.js +22 -0
  98. package/dist/lib/json-helpers.js.map +1 -0
  99. package/dist/lib/lifecycle-manager/index.cjs +5594 -0
  100. package/dist/lib/lifecycle-manager/index.cjs.map +1 -0
  101. package/dist/lib/lifecycle-manager/index.d.cts +2044 -0
  102. package/dist/lib/lifecycle-manager/index.d.ts +2044 -0
  103. package/dist/lib/lifecycle-manager/index.js +5543 -0
  104. package/dist/lib/lifecycle-manager/index.js.map +1 -0
  105. package/dist/lib/logger/index.cjs +2514 -0
  106. package/dist/lib/logger/index.cjs.map +1 -0
  107. package/dist/lib/logger/index.d.cts +630 -0
  108. package/dist/lib/logger/index.d.ts +630 -0
  109. package/dist/lib/logger/index.js +2470 -0
  110. package/dist/lib/logger/index.js.map +1 -0
  111. package/dist/lib/padding-utils.cjs +77 -0
  112. package/dist/lib/padding-utils.cjs.map +1 -0
  113. package/dist/lib/padding-utils.d.cts +44 -0
  114. package/dist/lib/padding-utils.d.ts +44 -0
  115. package/dist/lib/padding-utils.js +46 -0
  116. package/dist/lib/padding-utils.js.map +1 -0
  117. package/dist/lib/process-signal-manager.cjs +1306 -0
  118. package/dist/lib/process-signal-manager.cjs.map +1 -0
  119. package/dist/lib/process-signal-manager.d.cts +305 -0
  120. package/dist/lib/process-signal-manager.d.ts +305 -0
  121. package/dist/lib/process-signal-manager.js +1269 -0
  122. package/dist/lib/process-signal-manager.js.map +1 -0
  123. package/dist/lib/promise-protected-resolver.cjs +828 -0
  124. package/dist/lib/promise-protected-resolver.cjs.map +1 -0
  125. package/dist/lib/promise-protected-resolver.d.cts +17 -0
  126. package/dist/lib/promise-protected-resolver.d.ts +17 -0
  127. package/dist/lib/promise-protected-resolver.js +791 -0
  128. package/dist/lib/promise-protected-resolver.js.map +1 -0
  129. package/dist/lib/retry-utils/index.cjs +2183 -0
  130. package/dist/lib/retry-utils/index.cjs.map +1 -0
  131. package/dist/lib/retry-utils/index.d.cts +321 -0
  132. package/dist/lib/retry-utils/index.d.ts +321 -0
  133. package/dist/lib/retry-utils/index.js +2133 -0
  134. package/dist/lib/retry-utils/index.js.map +1 -0
  135. package/dist/lib/safe-handle-callback.cjs +818 -0
  136. package/dist/lib/safe-handle-callback.cjs.map +1 -0
  137. package/dist/lib/safe-handle-callback.d.cts +43 -0
  138. package/dist/lib/safe-handle-callback.d.ts +43 -0
  139. package/dist/lib/safe-handle-callback.js +780 -0
  140. package/dist/lib/safe-handle-callback.js.map +1 -0
  141. package/dist/lib/serialize-error/index.cjs +93 -0
  142. package/dist/lib/serialize-error/index.cjs.map +1 -0
  143. package/dist/lib/serialize-error/index.d.cts +26 -0
  144. package/dist/lib/serialize-error/index.d.ts +26 -0
  145. package/dist/lib/serialize-error/index.js +64 -0
  146. package/dist/lib/serialize-error/index.js.map +1 -0
  147. package/dist/lib/single-event-observer.cjs +841 -0
  148. package/dist/lib/single-event-observer.cjs.map +1 -0
  149. package/dist/lib/single-event-observer.d.cts +54 -0
  150. package/dist/lib/single-event-observer.d.ts +54 -0
  151. package/dist/lib/single-event-observer.js +803 -0
  152. package/dist/lib/single-event-observer.js.map +1 -0
  153. package/dist/lib/sleep.cjs +37 -0
  154. package/dist/lib/sleep.cjs.map +1 -0
  155. package/dist/lib/sleep.d.cts +11 -0
  156. package/dist/lib/sleep.d.ts +11 -0
  157. package/dist/lib/sleep.js +12 -0
  158. package/dist/lib/sleep.js.map +1 -0
  159. package/dist/lib/strings.cjs +186 -0
  160. package/dist/lib/strings.cjs.map +1 -0
  161. package/dist/lib/strings.d.cts +107 -0
  162. package/dist/lib/strings.d.ts +107 -0
  163. package/dist/lib/strings.js +149 -0
  164. package/dist/lib/strings.js.map +1 -0
  165. package/dist/lib/tmp-dir.cjs +254 -0
  166. package/dist/lib/tmp-dir.cjs.map +1 -0
  167. package/dist/lib/tmp-dir.d.cts +63 -0
  168. package/dist/lib/tmp-dir.d.ts +63 -0
  169. package/dist/lib/tmp-dir.js +211 -0
  170. package/dist/lib/tmp-dir.js.map +1 -0
  171. package/dist/lib/unix-time-helpers.cjs +53 -0
  172. package/dist/lib/unix-time-helpers.cjs.map +1 -0
  173. package/dist/lib/unix-time-helpers.d.cts +56 -0
  174. package/dist/lib/unix-time-helpers.d.ts +56 -0
  175. package/dist/lib/unix-time-helpers.js +24 -0
  176. package/dist/lib/unix-time-helpers.js.map +1 -0
  177. package/package.json +220 -0
@@ -0,0 +1,305 @@
1
+ /**
2
+ * The shutdown signal types that can trigger the shutdown callback
3
+ */
4
+ type ShutdownSignal = 'SIGINT' | 'SIGTERM' | 'SIGTRAP';
5
+ /**
6
+ * Status information about what the manager is attached to
7
+ */
8
+ interface ProcessSignalManagerStatus {
9
+ /**
10
+ * Whether the manager is currently attached to signals and keypresses
11
+ */
12
+ isAttached: boolean;
13
+ /**
14
+ * Which handlers are registered
15
+ */
16
+ handlers: {
17
+ /**
18
+ * Whether a shutdown handler is registered
19
+ */
20
+ shutdown: boolean;
21
+ /**
22
+ * Whether a reload handler is registered
23
+ */
24
+ reload: boolean;
25
+ /**
26
+ * Whether an info handler is registered
27
+ */
28
+ info: boolean;
29
+ /**
30
+ * Whether a debug handler is registered
31
+ */
32
+ debug: boolean;
33
+ };
34
+ /**
35
+ * What events are currently being listened for (only populated when isListening is true)
36
+ */
37
+ listeningFor: {
38
+ /**
39
+ * Listening for shutdown signals (SIGINT, SIGTERM, SIGTRAP)
40
+ */
41
+ shutdownSignals: boolean;
42
+ /**
43
+ * Listening for reload signal (SIGHUP)
44
+ */
45
+ reloadSignal: boolean;
46
+ /**
47
+ * Listening for info signal (SIGUSR1)
48
+ */
49
+ infoSignal: boolean;
50
+ /**
51
+ * Listening for debug signal (SIGUSR2)
52
+ */
53
+ debugSignal: boolean;
54
+ /**
55
+ * Listening for keypresses (Ctrl+C, Escape, R, I, D)
56
+ */
57
+ keypresses: boolean;
58
+ };
59
+ }
60
+ /**
61
+ * Configuration options for ProcessSignalManager
62
+ */
63
+ interface ProcessSignalManagerOptions {
64
+ /**
65
+ * Optional callback invoked when a shutdown signal is received.
66
+ *
67
+ * Triggered by:
68
+ * - Process signals: SIGINT, SIGTERM, SIGTRAP
69
+ * - Keyboard: Ctrl+C, Escape
70
+ */
71
+ onShutdownRequested?: (method: ShutdownSignal) => void | Promise<void>;
72
+ /**
73
+ * Optional callback invoked when reload is requested.
74
+ *
75
+ * Triggered by:
76
+ * - Process signal: SIGHUP
77
+ * - Keyboard: R key press (case-insensitive)
78
+ */
79
+ onReloadRequested?: () => void | Promise<unknown>;
80
+ /**
81
+ * Optional callback invoked when info/stats are requested.
82
+ *
83
+ * Triggered by:
84
+ * - Process signal: SIGUSR1
85
+ * - Keyboard: I key press (case-insensitive)
86
+ *
87
+ * Common uses: Print stats, health check, show metrics
88
+ */
89
+ onInfoRequested?: () => void | Promise<unknown>;
90
+ /**
91
+ * Optional callback invoked when debug mode is toggled or verbose info is requested.
92
+ *
93
+ * Triggered by:
94
+ * - Process signal: SIGUSR2
95
+ * - Keyboard: D key press (case-insensitive)
96
+ *
97
+ * Common uses: Toggle debug mode, dump full state, enable verbose logging
98
+ */
99
+ onDebugRequested?: () => void | Promise<unknown>;
100
+ /**
101
+ * Custom name for the shutdown callback used in error reporting.
102
+ * @default 'onShutdownRequested'
103
+ */
104
+ shutdownCallbackName?: string;
105
+ /**
106
+ * Custom name for the reload callback used in error reporting.
107
+ * @default 'onReloadRequested'
108
+ */
109
+ reloadCallbackName?: string;
110
+ /**
111
+ * Custom name for the info callback used in error reporting.
112
+ * @default 'onInfoRequested'
113
+ */
114
+ infoCallbackName?: string;
115
+ /**
116
+ * Custom name for the debug callback used in error reporting.
117
+ * @default 'onDebugRequested'
118
+ */
119
+ debugCallbackName?: string;
120
+ /**
121
+ * Throttle interval in milliseconds for keyboard events (leading-edge rate limiting).
122
+ * Allows an action to trigger at most once per interval. First press fires immediately,
123
+ * subsequent presses within the window are ignored.
124
+ * This prevents accidental double-triggers while allowing predictable repeated actions.
125
+ *
126
+ * Note: This only affects keyboard events, not process signals.
127
+ * Process signals are never throttled as they may come from external sources
128
+ * that expect immediate handling.
129
+ *
130
+ * @default 200 (200ms throttle, allowing 5 triggers per second maximum)
131
+ * @example 300 // Custom 300ms throttle (3.33 triggers per second max)
132
+ * @example 0 // Disable throttling entirely
133
+ */
134
+ keypressThrottleMS?: number;
135
+ }
136
+ /**
137
+ * Manages process signals and keyboard events for graceful shutdown, reload, and info/debug functionality.
138
+ *
139
+ * Handles:
140
+ * - Shutdown signals: SIGINT, SIGTERM, SIGTRAP
141
+ * - Reload signal: SIGHUP
142
+ * - Info signal: SIGUSR1
143
+ * - Debug signal: SIGUSR2
144
+ * - Keyboard shortcuts: Ctrl+C, Escape (shutdown), R (reload), I (info), D (debug)
145
+ * All letter keys are case-insensitive
146
+ *
147
+ * All callbacks are executed safely with automatic error handling.
148
+ */
149
+ declare class ProcessSignalManager {
150
+ private readonly instanceID;
151
+ private onShutdownRequested?;
152
+ private onReloadRequested?;
153
+ private onInfoRequested?;
154
+ private onDebugRequested?;
155
+ private shutdownCallbackName;
156
+ private reloadCallbackName;
157
+ private infoCallbackName;
158
+ private debugCallbackName;
159
+ private shutdownSignalListeners?;
160
+ private reloadSignalListener?;
161
+ private infoSignalListener?;
162
+ private debugSignalListener?;
163
+ private keypressHandler?;
164
+ private _isAttached;
165
+ private keypressThrottleMS;
166
+ private lastActionTimes;
167
+ constructor(options: ProcessSignalManagerOptions);
168
+ /**
169
+ * Check if the manager is currently attached to signals and keypresses.
170
+ */
171
+ get isAttached(): boolean;
172
+ /**
173
+ * Get detailed status information about what the manager is attached to.
174
+ *
175
+ * @returns Status object with handler registration and attachment state
176
+ */
177
+ getStatus(): ProcessSignalManagerStatus;
178
+ /**
179
+ * Attach signal handlers and start listening for process signals and keyboard events.
180
+ * Idempotent - calling multiple times has no effect.
181
+ */
182
+ attach(): void;
183
+ /**
184
+ * Detach signal handlers and stop listening for process signals and keyboard events.
185
+ * Cleans up all event listeners and restores stdin to normal mode.
186
+ *
187
+ * Idempotent - calling multiple times has no effect.
188
+ */
189
+ detach(): void;
190
+ /**
191
+ * Manually trigger a shutdown event
192
+ * if the manager is attached and a shutdown handler is registered
193
+ *
194
+ * @param method - The shutdown method (SIGINT, SIGTERM, or SIGTRAP) that will be passed to the shutdown callback
195
+ * @param shouldBypassAttachCheck - If true, triggers the callback even when not attached (useful for testing)
196
+ */
197
+ triggerShutdown(method: ShutdownSignal, shouldBypassAttachCheck?: boolean): void;
198
+ /**
199
+ * Manually trigger a reload event
200
+ * if the manager is attached and a reload handler is registered
201
+ *
202
+ * @param shouldBypassAttachCheck - If true, triggers the callback even when not attached (useful for testing)
203
+ */
204
+ triggerReload(shouldBypassAttachCheck?: boolean): void;
205
+ /**
206
+ * Manually trigger an info event
207
+ * if the manager is attached and an info handler is registered
208
+ *
209
+ * @param shouldBypassAttachCheck - If true, triggers the callback even when not attached (useful for testing)
210
+ */
211
+ triggerInfo(shouldBypassAttachCheck?: boolean): void;
212
+ /**
213
+ * Manually trigger a debug event
214
+ * if the manager is attached and a debug handler is registered
215
+ *
216
+ * @param shouldBypassAttachCheck - If true, triggers the callback even when not attached (useful for testing)
217
+ */
218
+ triggerDebug(shouldBypassAttachCheck?: boolean): void;
219
+ /**
220
+ * Check if an action should be throttled based on the last time it was successfully triggered.
221
+ * Uses leading-edge throttle: first press fires immediately, subsequent presses within the
222
+ * throttle window are ignored. Only updates timestamp when action is allowed (not throttled).
223
+ *
224
+ * This is the standard pattern for keyboard shortcuts and prevents accidental double-triggers
225
+ * while allowing predictable repeated actions at a maximum rate.
226
+ *
227
+ * @param action - The action type to check throttling for
228
+ * @returns true if the action should be throttled (ignored), false otherwise
229
+ */
230
+ private shouldThrottle;
231
+ /**
232
+ * Register handlers for all shutdown signals (SIGINT, SIGTERM, SIGTRAP) if callback is provided.
233
+ * Each signal will trigger the shutdown callback with the appropriate method.
234
+ */
235
+ private listenForShutdownSignals;
236
+ /**
237
+ * Remove handlers for all shutdown signals if they were registered.
238
+ * Uses the same function references to ensure proper cleanup.
239
+ */
240
+ private stopListeningForShutdownSignals;
241
+ /**
242
+ * Register handler for SIGHUP signal if reload callback is provided.
243
+ * SIGHUP is commonly used to trigger configuration reloads.
244
+ */
245
+ private listenForReloadSignal;
246
+ /**
247
+ * Remove handler for SIGHUP signal.
248
+ * Uses the same function reference to ensure proper cleanup.
249
+ */
250
+ private stopListeningForReloadSignal;
251
+ /**
252
+ * Register handler for SIGUSR1 signal if info callback is provided.
253
+ * SIGUSR1 is commonly used for printing stats, health checks, etc.
254
+ */
255
+ private listenForInfoSignal;
256
+ /**
257
+ * Remove handler for SIGUSR1 signal.
258
+ * Uses the same function reference to ensure proper cleanup.
259
+ */
260
+ private stopListeningForInfoSignal;
261
+ /**
262
+ * Register handler for SIGUSR2 signal if debug callback is provided.
263
+ * SIGUSR2 is commonly used for toggling debug mode, dumping state, etc.
264
+ */
265
+ private listenForDebugSignal;
266
+ /**
267
+ * Remove handler for SIGUSR2 signal.
268
+ * Uses the same function reference to ensure proper cleanup.
269
+ */
270
+ private stopListeningForDebugSignal;
271
+ /**
272
+ * Enable keyboard event listening if stdin is a TTY.
273
+ * Sets stdin to raw mode and listens for Ctrl+C, Escape, R, I, and D keypresses.
274
+ *
275
+ * Note: Letter keys are case-insensitive (R/r, I/i, D/d all work).
276
+ *
277
+ * Uses add-then-check pattern to prevent race conditions:
278
+ * 1. Add ourselves to attachedInstances first
279
+ * 2. Check if we're the first (size === 1) to enable raw mode
280
+ * This ensures no gap where another instance could read stale state.
281
+ */
282
+ private listenForKeyPresses;
283
+ /**
284
+ * Helper to clean up keypress handler registration on error.
285
+ * Removes handler, clears instance from shared state, and restores raw mode if needed.
286
+ *
287
+ * @param shared - The shared state object
288
+ * @param didAttemptRawModeEnable - If true, we attempted to enable raw mode (even if ownership wasn't recorded).
289
+ * This handles the edge case where setRawMode(true) throws after actually enabling raw mode.
290
+ */
291
+ private cleanupKeypressHandler;
292
+ /**
293
+ * Restore stdin to normal mode and clean up keypress listener.
294
+ * Uses remove-then-check pattern (mirror of add-then-check in attach):
295
+ * 1. Remove ourselves from attachedInstances first
296
+ * 2. Check if we're the last (size === 0) to disable raw mode and pause stdin
297
+ *
298
+ * Note: Can be called even if keypressHandler is undefined (e.g., during error recovery).
299
+ * In that case, we still update shared state and attempt terminal restoration if we
300
+ * were the recorded raw mode owner.
301
+ */
302
+ private restoreStdin;
303
+ }
304
+
305
+ export { ProcessSignalManager, type ProcessSignalManagerOptions, type ProcessSignalManagerStatus, type ShutdownSignal };