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

@asaidimu/utils-class

v2.0.2

Published

Class management utilities

Readme

@asaidimu/utils-class

Advanced Class Management & Observability for TypeScript

A powerful TypeScript library providing advanced class factory patterns with built-in lifecycle observation, robust singleton management, and integrated telemetry for comprehensive application monitoring.

npm version License Build Status


Quick Links


Overview & Features

@asaidimu/utils-class is a versatile utility library designed to streamline class creation, manage instance lifecycles, and provide deep observability into your application's runtime behavior. At its core, it offers manage, a highly configurable factory function that goes beyond standard class constructors. It introduces advanced patterns like robust singleton management (global or parameter-based), automatic instance cleanup, and a powerful observation mechanism to monitor object creation, property access, and method calls.

Complementing manage, the library provides TelemetryAdapter, a ready-to-use solution for integrating these observations with your observability stack. It collects, buffers, and sends structured logs (to Loki) and metrics (to Mimir), giving you real-time insights into your application's performance and health. This combination empowers developers to build more maintainable, scalable, and operationally transparent systems.

🚨 IMPORTANT NOTE: Current Version Status 🚨

Please be aware that the currently published version of @asaidimu/utils-class (version 1.0.0) contains a stubbed implementation for the manage function. This means the core functionality described below (instance management, singleton patterns, observation, and telemetry) is not yet active or fully functional in the index.js or index.mjs entry points. The detailed features and usage examples provided in this README describe the intended design and future capabilities of the library as it progresses towards a stable release.

We are actively working on fixing the underlying code and passing all tests to enable these features. Thank you for your understanding and patience!


Key Features (Intended/Planned)

🚀 manage:

  • Flexible Class Instantiation: Create classes from plain object initializers (sync or async).
  • Automated Cleanup: Register cleanup callbacks for instances, integrating with JavaScript's FinalizationRegistry for automatic resource management.
  • Robust Singleton Patterns: Implement global singletons or parameter-based singletons using keySelector for dynamic instance caching.
  • Lifecycle & Usage Observation: Monitor critical events including:
    • create: Instance creation.
    • cleanup: Instance garbage collection and cleanup execution.
    • access: Property read access.
    • method-call: Method execution (sync/async, success/failure, duration).
    • error: Errors during creation, cleanup, or method calls.
  • Configurable Sampling: Control the volume of observation events to optimize performance.
  • Instance Registry: Get runtime insights into active and disposed instances.

TelemetryAdapter:

  • LGTM Stack Integration: Out-of-the-box support for sending telemetry data to Loki (logs) and Mimir (metrics).
  • Event Buffering & Flushing: Efficiently collect and send events in batches, with configurable buffer size and flush intervals.
  • Automatic Retries: Robust error handling for failed telemetry uploads with exponential backoff.
  • Comprehensive Metrics: Tracks core metrics like total instances, method call counts, method durations (histograms), and error rates.
  • Authentication Support: Securely send data with basic authentication.
  • Dynamic Control: Enable and disable telemetry collection at runtime.
  • Data Sanitization: Automatically cleans up sensitive or excessively large data fields before sending.

Installation & Setup

Prerequisites

  • Node.js: Version 18 or higher (LTS recommended)
  • npm or Yarn or Bun: A package manager for Node.js

Installation Steps

Install the library using your preferred package manager:

bun add @asaidimu/utils-class
# or
npm install @asaidimu/utils-class
# or
yarn add @asaidimu/utils-class

Configuration (for Telemetry)

To utilize the telemetry features (once they are active in a future release), you'll need to configure the TelemetryRegistry with your LGTM stack endpoints and application metadata.

import { TelemetryRegistry, type TelemetryConfig } from '@asaidimu/utils-class';

const telemetryConfig: TelemetryConfig = {
  lgtm: {
    lokiUrl: 'http://localhost:3100/loki/api/v1/push', // Your Loki endpoint
    tempoUrl: 'http://localhost:3200/api/traces', // Not directly used by TelemetryAdapter currently, but part of LGTM config
    mimirUrl: 'http://localhost:9009/api/v1/push', // Your Mimir endpoint
    auth: { // Optional: if your LGTM stack requires basic auth
      username: 'your-username',
      password: 'your-password'
    }
  },
  metadata: {
    serviceName: 'my-awesome-app',
    environment: 'development',
    version: '1.0.0',
    labels: { // Optional additional labels for all telemetry
      team: 'frontend',
      region: 'us-east-1'
    }
  },
  bufferConfig: {
    size: 50,           // Buffer up to 50 events before flushing
    flushInterval: 2000, // Flush every 2 seconds if buffer is not full
    maxRetries: 5,      // Max retries for failed requests
    retryDelay: 500,    // Initial retry delay in ms
    maxBufferAge: 60000 // Drop events older than 60 seconds from buffer
  },
  enabledByDefault: true, // Optional: default to true
  metrics: [ // Optional: Define custom metrics
    // { name: 'my_custom_counter', type: 'counter', description: 'A custom counter', labels: ['status'] }
  ]
};

// Initialize the global TelemetryRegistry (it's a singleton)
const telemetry = new TelemetryRegistry(telemetryConfig);

// You can observe directly or pass the adapter.observe method to manage
// const observer = telemetry.observe('MyClass');

// To disable/enable telemetry dynamically:
// telemetry.disable();
// telemetry.enable();

Verification

After installation, you can verify it by importing the library. Please note that the primary manage function is currently a stub.

import { manage, TelemetryRegistry } from '@asaidimu/utils-class';

console.log('Library imported successfully!');

// The manage function currently logs a message indicating it's a stub.
const MyClass = manage(() => ({ value: 1 }));
const instance = new MyClass(); // This will log "THIS METHOD IS A STUB UNTIL WE FIX THE CODE AND TESTS PASS"
// The 'instance' will be an empty object or whatever the stub returns.

Usage Documentation

⚠ Note: The examples below demonstrate the intended usage of manage and TelemetryRegistry once the stubbed functionality is fully implemented. In the current 1.0.0 version, these examples will not produce the described behavior due to the manage stub.

manage Fundamentals

The manage function is the primary entry point for creating managed classes. It takes an initializer function and an optional options object.

Basic Class Creation

The initializer function should return an object that defines the instance's properties and methods.

import { manage } from '@asaidimu/utils-class';

// 1. Synchronous initializer
interface GreeterInstance {
  message: string;
  greet(): string;
}

const GreeterClass = manage<GreeterInstance, { initialMessage: string }>(
  (params) => ({
    message: params.initialMessage,
    greet() { return `Hello, ${this.message}!`; }
  })
);

const greeter = new GreeterClass({ initialMessage: 'World' });
console.log(greeter.greet()); // Expected Output: Hello, World!

// 2. Async Initializer (returns a Promise)
interface AsyncDataLoader {
  data: string;
  fetchData(): Promise<string>;
}

const AsyncClass = manage<AsyncDataLoader, { id: number }>(
  async (params) => {
    const fetchedData = await new Promise<string>(resolve => setTimeout(() => resolve(`Data for ${params.id}`), 100));
    return {
      data: fetchedData,
      async fetchData() { return this.data; }
    };
  }
);

(async () => {
  const instancePromise = new AsyncClass({ id: 123 });
  console.log(instancePromise instanceof Promise); // Expected Output: true

  const instance = await instancePromise;
  console.log(instance.data); // Expected Output: Data for 123
})();

Class with Cleanup Logic

Your initializer can optionally return a tuple [instance, cleanupFunction] to define a cleanup callback that will be invoked when the instance is garbage collected.

import { manage } from '@asaidimu/utils-class';

interface ResourceHolder {
  id: string;
  release(): void;
}

const ResourceClass = manage<ResourceHolder, { name: string }>(
  (params) => {
    const resourceId = `resource-${params.name}-${Date.now()}`;
    console.log(`Resource ${resourceId} acquired.`);

    const instance: ResourceHolder = {
      id: resourceId,
      release: () => console.log(`Resource ${resourceId} explicitly released.`)
    };

    const cleanup = () => {
      console.log(`Resource ${resourceId} automatically released (GC).`);
      // Perform actual resource cleanup here (e.g., close database connections, clear timers)
    };

    return [instance, cleanup];
  }
);

(async () => {
  let res = new ResourceClass({ name: 'db-connection' });
  // The 'Resource acquired' message will be logged immediately.

  // If `res` goes out of scope, the cleanup function will eventually be called by GC.
  // For immediate cleanup, you'd typically have a `dispose` method on the instance itself.
  res.release(); // Explicit release

  // To trigger GC for testing (not recommended in production, non-deterministic):
  // res = null as any;
  // global.gc && global.gc(); // Requires Node.js --expose-gc flag
})();

Factory Function Mode

Instead of a class constructor, manage can return a direct factory function by setting factory: true in options.

import { manage } from '@asaidimu/utils-class';

interface ServiceInstance {
  id: string;
}

const createService = manage<ServiceInstance, { name: string }>(
  (params) => ({ id: `service-${params.name}` }),
  { factory: true } // Returns a function instead of a class
);

const myService1 = createService({ name: 'auth' });
const myService2 = createService({ name: 'logger' });

console.log(myService1.id); // Expected Output: service-auth
console.log(myService2.id); // Expected Output: service-logger

Singleton Management

manage supports two modes of singleton management: global and parameter-based.

Global Singleton

Returns the exact same instance on every call.

import { manage } from '@asaidimu/utils-class';

interface GlobalConfig {
  value: number;
}

const ConfigSingleton = manage<GlobalConfig, {}>(
  () => ({ value: Math.random() }),
  { singleton: true } // Enable global singleton
);

const config1 = new ConfigSingleton();
const config2 = new ConfigSingleton();

console.log(config1 === config2);       // Expected Output: true
console.log(config1.value === config2.value); // Expected Output: true

Parameter-Based Singleton

Creates a new instance for each unique set of constructor parameters (or derived key).

import { manage } from '@asaidimu/utils-class';

interface CacheInstance {
  id: string;
  createdAt: number;
}

const CacheManager = manage<CacheInstance, { cacheKey: string }>(
  (params) => ({
    id: `cache-${params.cacheKey}`,
    createdAt: Date.now()
  }),
  {
    keySelector: (params) => params.cacheKey // Use `cacheKey` parameter as the singleton key
  }
);

const cacheA1 = new CacheManager({ cacheKey: 'user-data' });
const cacheA2 = new CacheManager({ cacheKey: 'user-data' }); // Returns existing instance
const cacheB = new CacheManager({ cacheKey: 'product-data' }); // Creates new instance

console.log(cacheA1 === cacheA2);       // Expected Output: true
console.log(cacheA1 === cacheB);        // Expected Output: false
console.log(cacheA1.createdAt === cacheA2.createdAt); // Expected Output: true
console.log(cacheA1.createdAt !== cacheB.createdAt);  // Expected Output: true

Lifecycle Observation

The observer option allows you to receive detailed events about class instances. This is crucial for monitoring and debugging.

import { manage, type InstanceEvent } from '@asaidimu/utils-class';

// Define a custom observer function
const myCustomObserver = (event: InstanceEvent<any, any>) => {
  console.log(`[${event.type.toUpperCase()}] Instance: ${event.instanceId}`);
  if (event.property) console.log(`  Property: ${String(event.property)}`);
  if (event.time !== undefined) console.log(`  Duration: ${event.time.toFixed(2)}ms`);
  if (event.error) console.error(`  Error: ${event.error.message}`);
  console.log('---');
};

interface MyObservableClassInstance {
  value: number;
  increment(amount: number): number;
  asyncFetch(): Promise<string>;
  failingMethod(): void;
}

const MyObservableClass = manage<MyObservableClassInstance, { initialValue: number }>(
  (params) => ({
    value: params.initialValue,
    increment(amount: number) {
      this.value += amount;
      return this.value;
    },
    async asyncFetch() {
      await new Promise(resolve => setTimeout(resolve, 50));
      return 'data fetched';
    },
    failingMethod() {
      throw new Error('This method always fails!');
    }
  }),
  {
    observer: myCustomObserver, // Pass your observer function
    sampling: { global: 1 } // Ensure all events are reported (default is 1)
  }
);

const instance = new MyObservableClass({ initialValue: 100 });
// Expected Output: [CREATE] Instance: inst_... (initialization event)

console.log('Initial value:', instance.value); // Property access triggers event
// Expected Output: [ACCESS] Instance: inst_... Property: value

instance.increment(10); // Method call triggers event
// Expected Output: [METHOD-CALL] Instance: inst_... Property: increment ...

(async () => {
  await instance.asyncFetch(); // Async method call triggers event
  // Expected Output: [METHOD-CALL] Instance: inst_... Property: asyncFetch ... async: true ...

  try {
    instance.failingMethod(); // Failing method call triggers error event
  } catch (e) {
    console.error('Caught expected error.');
    // Expected Output: [METHOD-CALL] Instance: inst_... Property: failingMethod ... success: false ... Error: This method always fails!
  }
})();

// When 'instance' is eventually garbage collected, a 'CLEANUP' event will be reported.

Sampling Configuration

Reduce overhead by sampling observation events:

import { manage } from '@asaidimu/utils-class';

const observer = (event: any) => console.log(`Observed: ${event.type}`);

const SampledClass = manage(() => ({
  doSomething() {}
}), {
  observer: observer,
  sampling: {
    global: 0.1, // Only 10% of all events will be reported
    eventTypes: {
      'method-call': 0.5, // 50% of method calls
      'create': 1 // 100% of creation events (overrides global for this type)
    }
  }
});

const instance = new SampledClass();
instance.doSomething();
instance.doSomething();
// Events will be reported based on the configured probabilities.

Telemetry Integration (LGTM Stack)

The TelemetryAdapter is a pre-built observer that formats and sends events to Loki (logs) and Mimir (metrics). The TelemetryRegistry is a singleton instance of TelemetryAdapter for easy access.

import { manage, TelemetryRegistry, type TelemetryConfig } from '@asaidimu/utils-class';

// 1. Configure and initialize TelemetryRegistry
const telemetryConfig: TelemetryConfig = {
  lgtm: {
    lokiUrl: 'http://localhost:3100/loki/api/v1/push',
    tempoUrl: 'http://localhost:3200/api/traces', // Not used by observer.ts currently
    mimirUrl: 'http://localhost:9009/api/v1/push',
  },
  metadata: {
    serviceName: 'my-app-telemetry-demo',
    environment: 'staging'
  },
  bufferConfig: { size: 10, flushInterval: 1000 }
};

const telemetry = new TelemetryRegistry(telemetryConfig); // This creates or retrieves the singleton instance

// 2. Create a class and link it to the telemetry observer
interface MyServiceInstance {
  processData(data: string): string;
  generateError(): void;
}

const MyService = manage<MyServiceInstance, { id: number }>(
  (params) => ({
    processData(data: string) {
      console.log(`Processing data for service ${params.id}: ${data}`);
      return `Processed: ${data.toUpperCase()}`;
    },
    generateError() {
      throw new Error(`Error from MyService ${params.id}`);
    }
  }),
  {
    observer: telemetry.observe('MyService'), // Pass the specific observer for 'MyService' class
    sampling: { global: 1 } // Ensure all events are reported for this example
  }
);

// 3. Use your class
const service1 = new MyService({ id: 1 });
service1.processData('hello world');

const service2 = new MyService({ id: 2 });
service2.processData('another message');

try {
  service1.generateError();
} catch (e) {
  console.error('Caught expected error from service1.');
}

// Events are buffered and sent periodically to Loki and Mimir.
// You can force a flush for testing/shutdown:
(async () => {
  await telemetry.cleanup(); // Flushes remaining events and stops intervals
  console.log('Telemetry cleaned up.');
})();

Expected telemetry data sent to Loki (logs):

  • Log entries for create, access, method-call, error events, including instance details, class tag, and operation timings.

Expected telemetry data sent to Mimir (metrics):

  • class_instances_total{class="MyService",service="my-app-telemetry-demo",environment="staging"} (gauge)
  • class_method_calls_total{class="MyService",method="processData",success="true",async="false",service="..."} (counter)
  • class_method_duration_seconds_bucket{class="MyService",method="processData",le="..."} (histogram buckets)
  • class_errors_total{class="MyService",error_type="Error",phase="usage",service="..."} (counter)

Instance Registry

Both manage and the factory function it can return provide a static getInstanceRegistry() method to inspect currently tracked instances.

import { manage } from '@asaidimu/utils-class';

const MyTrackedClass = manage(() => ({
  id: Math.random(),
}));

const instance1 = new MyTrackedClass();
const instance2 = new MyTrackedClass();

console.log('Instance Registry:', MyTrackedClass.getInstanceRegistry());
/* Expected Output example:
{
  activeCount: 2,
  totalTracked: 2,
  instances: [
    {
      id: 'inst_1_...',
      createdAt: <Date>,
      lastActiveAt: <Date>,
      age: <number>ms,
      isDisposed: false,
      hasCleanup: false
    },
    // ... for instance 2
  ]
}
*/

// If you returned a factory function:
const createMyTrackedService = manage(() => ({ name: 'test' }), { factory: true });
const service = createMyTrackedService();
console.log('Service Factory Registry:', createMyTrackedService.getInstanceRegistry());

Project Architecture

The @asaidimu/utils-class library is structured around two core modules: factory and observer.

src/class/
├── factory.ts            # Core logic for manage, instance management, and observation proxying
├── observer.ts           # TelemetryAdapter for LGTM integration, event buffering, and metrics
├── index.ts              # Re-exports from factory and observer for easy import (currently contains stub)
├── factory.test.ts       # Vitest tests for manage
├── observer.test.ts      # Vitest tests for TelemetryAdapter
└── README.md             # This document

Core Components

  • manage<T, P>(initializer, options) (exposed from index.ts, implemented in factory.ts): The primary factory function. It takes an initializer (a function returning an instance object or [instance, cleanup]) and options to configure behavior like singleton mode, key-based caching, and event observation. It leverages Proxy for method and property access interception, and FinalizationRegistry/WeakRef for garbage collection-aware cleanup and instance tracking.
  • InstanceEvent<T, P> (in factory.ts): A TypeScript type definition for the structured events generated by manage's observation mechanism. These events capture details about creation, cleanup, errors, property accesses, and method calls.
  • TelemetryAdapter<T, P>(config) (in observer.ts): A class that acts as an observer for InstanceEvents. It buffers these events and transforms them into appropriate formats for Loki (logs) and Mimir (metrics), then sends them via fetch. It manages buffering, retries, and authentication.
  • TelemetryRegistry (in observer.ts): A singleton instance of TelemetryAdapter, created using manage itself, ensuring a single, globally accessible telemetry client.

Data Flow (Intended)

  1. Instance Creation/Usage: When a class generated by manage is instantiated, or its methods/properties are accessed, InstanceEvent objects are generated internally.
  2. Observation Callback: These InstanceEvents are passed to the observer callback provided in manage options.
  3. Telemetry Adapter: If TelemetryAdapter.observe() is used as the observer, it receives these events.
  4. Buffering & Metrics: The TelemetryAdapter buffers the events and updates its internal metric state.
  5. Flushing: Periodically (or when the buffer is full), TelemetryAdapter formats the buffered events into Loki-compatible log streams and Mimir-compatible Prometheus text format metrics.
  6. Transmission: The formatted data is sent to the configured Loki and Mimir endpoints using fetch.
  7. LGTM Stack: Loki stores the logs, and Mimir ingests the metrics, making them available for querying and visualization (e.g., in Grafana).

Development & Contributing

Development Setup

To set up the project for local development:

  1. Clone the repository:
    git clone https://github.com/asaidimu/erp-utils.git # This module is part of a monorepo
    cd erp-utils/src/class # Navigate to this specific module
  2. Install dependencies:
    npm install
    # or
    yarn install
    # or
    bun install
  3. Build the project:
    npm run build
    # or
    yarn build
    # or
    bun run build

Scripts

  • npm test: Runs all unit tests using Vitest.
  • npm run build: Compiles TypeScript files to JavaScript.
  • npm run lint: Runs ESLint for code quality checks.
  • npm run format: Formats code using Prettier.

Testing

Tests are written using Vitest. Note that some test suites (Observation, TelemetryAdapter) are currently skipped in the source code (.skip) and will not run by default until the underlying functionality is stable.

To run tests:

npm test

To run tests in watch mode:

npm test -- --watch

Test coverage requirements are typically defined in the vitest.config.ts or package.json.

Contributing Guidelines

We welcome contributions! Please follow these steps:

  1. Fork the repository.
  2. Create a new branch for your feature or bug fix (git checkout -b feature/my-new-feature).
  3. Make your changes, ensuring they adhere to the existing coding style and standards.
  4. Write and run tests to cover your changes and ensure no regressions (npm test). Pay special attention to the currently skipped tests if your changes relate to observation or telemetry.
  5. Update documentation if your changes impact existing features or introduce new ones.
  6. Commit your changes using a descriptive commit message following Conventional Commits specifications (e.g., feat: add new observer option).
  7. Push your branch to your forked repository.
  8. Open a Pull Request to the main branch of the original repository.

Issue Reporting

If you find a bug or have a feature request, please open an issue on the GitHub Issues page. When reporting a bug, please include:

  • A clear and concise description of the issue.
  • Steps to reproduce the behavior.
  • Expected vs. actual behavior.
  • Any relevant error messages or console output.
  • Your environment details (Node.js version, OS, etc.).

Additional Information

Troubleshooting

  • manage does not work as expected:
    • As mentioned in the Overview, the manage function is currently a stub. It will not perform the described class management, singleton, or observation behaviors in the 0.0.0 version. This is the intended behavior until the stub is removed in a future release.
  • Telemetry not sending (once enabled):
    • Verify your lokiUrl and mimirUrl in TelemetryConfig.
    • Check network connectivity to your LGTM stack.
    • Ensure fetch is available in your environment (Node.js versions below 18 might need a polyfill, though it's typically global).
    • Check browser console/Node.js output for fetch errors.
    • Confirm your TelemetryAdapter is enabled.
  • Events not observed (once enabled):
    • Ensure observer option is correctly passed to manage.
    • Check sampling configuration; a very low global or eventType rate might prevent events from being reported.
    • Verify the observer function itself is logging or processing events.
  • Cleanup not triggering:
    • FinalizationRegistry relies on garbage collection, which is non-deterministic. Cleanup functions will eventually be called when the instance is no longer reachable, but there's no guarantee on when.
    • For immediate resource release, implement a dispose() method on your instances.

FAQ

Q: Why is manage a stub? A: The manage function in the current 0.0.0 version is a placeholder. This is part of the development process to ensure the core logic and tests are thoroughly validated before releasing the full functionality. We are actively working on it.

Q: What is the LGTM Stack? A: LGTM stands for Loki, Grafana, Tempo, Mimir. It's a suite of open-source tools from Grafana Labs for observability: - Loki: A log aggregation system for collecting logs. - Grafana: A visualization and dashboarding tool. - Tempo: A distributed tracing backend. - Mimir: A scalable, long-term storage for Prometheus metrics. @asaidimu/utils-class's TelemetryAdapter specifically integrates with Loki (for logs/events) and Mimir (for metrics).

Q: What is the performance impact of using manage and its observation features? A: manage uses JavaScript Proxy objects for observation. While proxies have a slight performance overhead compared to direct object access, it's generally negligible for most application use cases. The sampling option for the observer allows you to control the volume of events, significantly reducing the overhead of event processing and transmission if fine-grained monitoring isn't always required. TelemetryAdapter buffers events and flushes them asynchronously to minimize blocking the main thread.

Q: Can I use manage in a browser environment? A: Yes, manage and TelemetryAdapter are designed to work in both Node.js and browser environments. The TelemetryAdapter intelligently uses window.setInterval/clearInterval in browsers and globalThis.setInterval/clearInterval in Node.js, and fetch is a standard Web API.

Changelog / Roadmap

  • Changelog: See CHANGELOG.md for a history of changes.
  • Roadmap: Future plans include:
    • Enabling full manage functionality: Removing the stub and ensuring all tests pass.
    • Adding support for custom event properties in TelemetryAdapter.
    • More advanced sampling strategies.
    • Integration with other telemetry backends (e.g., OpenTelemetry).

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Inspired by various dependency injection and observability patterns in modern software architecture.
  • Built with TypeScript and tested with Vitest.