npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lifecycleion

v0.1.0

Published

A collection of foundational TypeScript utilities for managing application lifecycle, logging, retries, events, and common programming patterns

Readme

Lifecycleion v0.1.0

npm version

A collection of foundational TypeScript utilities for managing application lifecycle, logging, retries, events, and common programming patterns.

⚠️ Pre-1.0.0: Lifecycleion is maturing and usable, but still pre-1.0. The core APIs are stabilizing yet may still change before 1.0.0. Pin a version and review release notes when upgrading.

Why Lifecycleion?

Lifecycleion provides TypeScript utilities for application lifecycle orchestration, logging, retries, events, HTTP requests, and common programming patterns.

Key Features

  • 🌐 HTTP Client - Fluent request builder with Fetch, Node.js native, XHR, and Mock adapters, interceptors, observers, retries, cookies, and redirect control
  • 🚀 Lifecycle Management - Orchestrate startup, shutdown, and runtime control of application components with dependency resolution
  • 🪵 Flexible Logger - Sink-based logger with log levels, redaction, and service scoping
  • 🔄 Retry Utilities - Fixed and exponential backoff strategies with cancellation support
  • 📡 Event Systems - Event emitters for multiple event types and single-event observers with type safety
  • 🛡️ Error Handling - Serialize errors for IPC/RPC, format them as readable tables, and handle callbacks safely
  • 🔧 Common Utilities - ID generation (UUID, ULID, ObjectID), string manipulation, deep cloning, and more
  • 📦 Tree-shakeable - Import only what you need via subpath exports
  • 💪 TypeScript-first - TypeScript definitions for every published entry point

Installation

npm install lifecycleion
# or
yarn add lifecycleion
# or
bun add lifecycleion

Peer Dependency: tldts

Lifecycleion declares tldts as a required peer dependency. It carries the compiled Public Suffix List that http-client's CookieJar scopes cookies with and that domain-utils re-exports, and it is a peer rather than a direct dependency for two reasons: a compatible shared installation avoids duplicate PSL snapshots, and you can refresh the list by upgrading tldts within its supported range without waiting on a Lifecycleion release.

Ensure your installation includes a version of tldts satisfying ^7.4.10. If your package manager does not install peers automatically, or that behavior is disabled, install it explicitly:

npm install 'tldts@^7.4.10'

tldts is imported at module load by lifecycleion/http-client and lifecycleion/domain-utils. A missing peer prevents those entry points from loading. The peer allows consumers to update the PSL within the supported range, but does not itself guarantee that a dependency tree contains only one version.

For Node.js runtimes, Lifecycleion currently targets Node >=25. Some libraries, including safe-handle-callback, logger's error listener, and lru-cache's onChange, report errors on the standard global 'error' event channel: an ErrorEvent dispatched through the global EventTarget methods. Those are web-standard primitives, and browsers, Bun, and Deno expose them on globalThis natively.

Standalone rendering and redaction failures use that same channel when you have not set a handler, so a logger.registerReportErrorListener() records them like any other reported failure. Failures raised by the logger itself use a separate asynchronous diagnostic channel: its 'diagnostic' event, then diagnosticSinks (or the regular sinks when none were configured), then guarded console.error. Diagnostic writes do not run through the logger again. See Where Failures Go.

Node.js is a partial case: ErrorEvent is native in Node 25+, but globalThis is still not an EventTarget, so Lifecycleion automatically supplies the missing global event methods without overwriting native or user-installed implementations. See global-event-target.

Quick Example

import {
  LifecycleManager,
  BaseComponent,
} from 'lifecycleion/lifecycle-manager';
import { ConsoleSink, Logger } from 'lifecycleion/logger';
import { RetryRunner } from 'lifecycleion/retry-utils';

// Create a logger
const logger = new Logger({ sinks: [new ConsoleSink()] });

// Set up retry logic
const runner = new RetryRunner(
  { strategy: 'fixed', maxRetryAttempts: 3, delayMS: 1000 },
  async (reportResult) => {
    // Your operation here
    reportResult('success');
  },
);

await runner.run(true);

// Manage component lifecycle
class MyComponent extends BaseComponent {
  constructor() {
    super(logger, { name: 'my-component' });
  }

  async start() {
    logger.info('Starting component');
  }

  async stop() {
    logger.info('Stopping component');
  }
}

const manager = new LifecycleManager({ logger });
await manager.registerComponent(new MyComponent());

const startup = await manager.startAllComponents();

if (!startup.success) {
  await logger.close();
  throw new Error(startup.reason);
}

// Run the application, then release component and logger resources.
await manager.stopAllComponents();
await logger.close();

Tip: listen for lifecycle-manager:shutdown-completed when you want one place to react to shutdown results from manual stops, signals like SIGINT / SIGTERM, or logger-exit hooks. This is the centralized hook for logging or follow-up policy when timedOut is true or stalledComponents is non-empty. If timedOut is true, the payload reflects the result when the manager stopped waiting. A stop already in flight remains protected against per-component overlap, while exit handling and later shutdown/escalation attempts may proceed. Use repeated shutdown escalation separately when you want additional shutdown requests to retry or force behavior.

Available Libraries

Each library has reference documentation in the docs folder. Click a library name below for its API notes and examples.

| Library | Import Path | Description | | ------------------------------------------------------------------ | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | arrays | lifecycleion/arrays | Array utility functions for filtering, comparison, deduplication, and string manipulation | | ascii-tables | lifecycleion/ascii-tables | Key-value and multi-column ASCII tables with word wrapping, nesting, and emoji support | | clamp | lifecycleion/clamp | Number clamping utilities with safe handling for non-finite values and nullish inputs | | constants | lifecycleion/constants | Common string constants including whitespace helpers and Python-style character sets | | curly-brackets | lifecycleion/curly-brackets | String templating with {{placeholders}}, fallbacks, escaping, and compiled templates | | datamask | lifecycleion/datamask | Mask emails, domains, and strings by proportion, counting in characters so a cut never splits an emoji | | deep-clone | lifecycleion/deep-clone | Deep clone utility with circular reference detection for objects, arrays, Maps, Sets, and more | | dev-mode | lifecycleion/dev-mode | Runtime-settable dev/production mode flag with auto-detection from CLI args or NODE_ENV | | domain-utils | lifecycleion/domain-utils | Hardened helpers for normalizing and matching domains and origins for CORS and routing, with IDNA/TR46, IPv6, and wildcard semantics | | error-to-string | lifecycleion/error-to-string | Format errors into readable ASCII tables with support for nested info and sensitive field masking | | event-emitter | lifecycleion/event-emitter | Lightweight event emitter with protected and public variants, type safety, and memory management | | global-event-target | lifecycleion/global-event-target | Conservative polyfill giving globalThis the EventTarget methods on Node.js, so 'error' event dispatch works there | | http-client | lifecycleion/http-client (+ -node, -xhr, -mock) | Fluent HTTP client with Fetch, Node.js native, XHR, and Mock adapters, interceptors, observers, retries, cookies, and redirect control | | id-helpers | lifecycleion/id-helpers | Unified ID generation and validation for ObjectID, UUID v4, UUID v7, and ULID | | is-boolean | lifecycleion/is-boolean | Type guard to check if a value is a boolean | | is-function | lifecycleion/is-function | Check whether a value is a function | | is-number | lifecycleion/is-number | Type guards to check whether a value is a valid number, with and without finite enforcement | | is-plain-object | lifecycleion/is-plain-object | Type guard to check if a value is a plain object (not null, not an array) | | is-promise | lifecycleion/is-promise | Thenable/promise detection following the Promises/A+ specification | | json-helpers | lifecycleion/json-helpers | JSON formatting utilities | | lru-cache | lifecycleion/lru-cache | TTL-aware LRU cache with entry-count and size-based eviction, custom size calculators, and per-entry TTL overrides | | lifecycle-manager | lifecycleion/lifecycle-manager | Lifecycle orchestration for managing startup, shutdown, and runtime control of application components | | logger | lifecycleion/logger | Flexible sink-based logger with log levels, redaction, template strings, and service scoping | | padding-utils | lifecycleion/padding-utils | String padding utilities for left, right, and center alignment with a configurable pad character | | process-signal-manager | lifecycleion/process-signal-manager | Unified handler for process signals (SIGINT, SIGTERM, SIGHUP, etc.) and keyboard shortcuts with graceful shutdown and hot-reload support | | promise-protected-resolver | lifecycleion/promise-protected-resolver | Promise wrapper with resolveOnce and rejectOnce that guarantee a promise is only settled once | | retry-utils | lifecycleion/retry-utils | Retry logic with fixed and exponential backoff via RetryPolicy (low-level) and RetryRunner (high-level with events and cancellation) | | safe-handle-callback | lifecycleion/safe-handle-callback | Safely execute sync or async callbacks with automatic error reporting on the standard 'error' channel (ErrorEvent + global EventTarget) | | serialize-error | lifecycleion/serialize-error | Convert any Error into a plain JSON-serializable object and back again for IPC, RPCs, and database storage | | single-event-observer | lifecycleion/single-event-observer | Lightweight type-safe observer pattern for a single event type, with public and protected notify variants | | sleep | lifecycleion/sleep | Pause async execution for a given number of milliseconds | | strings | lifecycleion/strings | String type guard, case conversion (PascalCase, camelCase, CONSTANT_CASE), grapheme splitting, character filtering, and chopping helpers | | tmp-dir | lifecycleion/tmp-dir | Create uniquely named temporary directories with explicit cleanup, configurable prefix, postfix, and unsafe cleanup support | | stringify-value | lifecycleion/stringify-value | Render any value as a display string, or return it with parts redacted | | to-error | lifecycleion/to-error | Coerce any thrown or rejected value into an Error (toError), or describe it as a string that is always safe to read (describeError) | | unix-time-helpers | lifecycleion/unix-time-helpers | Unix timestamp utilities for seconds, milliseconds, high-resolution timing, and unit conversion |

Change Log

See changelog.md for version history and release notes.

Contributing

Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests on GitHub.

License

MIT License - see LICENSE file for details.