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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@gl-life/gl-life-core

v1.0.1

Published

Foundation package for GoodLife Sargam providing shared TypeScript types, utilities, error handling, logger, event bus, and configuration management

Readme

@gl-life/gl-life-core

npm version License

Foundation package for GoodLife Sargam - Production-ready TypeScript utilities for error handling, logging, configuration, and more.

Features

  • 🔒 Type-Safe Error Handling - Result and Option types for safe error handling
  • 📝 Structured Logging - JSON logging with context and levels
  • 🎯 Event System - Type-safe pub/sub with async support
  • ⚙️ Configuration Management - Environment variables with Zod validation
  • 🛠️ Utilities - Deep cloning, debounce, throttle, retry, validators
  • 100% TypeScript - Full type safety and IntelliSense support
  • 📦 Dual Exports - ESM and CommonJS support
  • 🧪 Well-Tested - Comprehensive test coverage

Installation

npm install @gl-life/gl-life-core
yarn add @gl-life/gl-life-core
pnpm add @gl-life/gl-life-core

Quick Start

import {
  Result,
  Logger,
  LogLevel,
  Config,
  EventBus,
  deepClone,
} from '@gl-life/gl-life-core';

// Safe error handling with Result type
const divide = (a: number, b: number): Result<number, string> => {
  if (b === 0) {
    return Result.err('Division by zero');
  }
  return Result.ok(a / b);
};

const result = divide(10, 2);
if (result.isOk()) {
  console.log('Result:', result.unwrap()); // 5
}

// Structured logging
const logger = new Logger({ level: LogLevel.INFO });
logger.info('Application started', { version: '1.0.0' });

// Event bus
const eventBus = new EventBus();
eventBus.subscribe('user:login', (data) => {
  console.log('User logged in:', data);
});
await eventBus.emit('user:login', { userId: 123 });

// Configuration with validation
import { z } from 'zod';

const schema = z.object({
  PORT: z.number().default(3000),
  HOST: z.string().default('localhost'),
});

const config = new Config({
  schema,
  envPrefix: 'APP_',
});

console.log(config.get('PORT')); // From APP_PORT env or default 3000

Core Types

Result<T, E>

Type-safe error handling without exceptions.

import { Result } from '@gl-life/gl-life-core';

// Create results
const success = Result.ok(42);
const failure = Result.err('Something went wrong');

// Check result
if (success.isOk()) {
  console.log(success.unwrap()); // 42
}

// Transform with map
const doubled = success.map(x => x * 2); // Ok(84)

// Chain operations
const result = Result.ok(10)
  .map(x => x * 2)
  .flatMap(x => x > 15 ? Result.ok(x) : Result.err('Too small'));

// Safe unwrapping
const value = result.unwrapOr(0); // Get value or default

Option

Handle nullable values safely.

import { Option } from '@gl-life/gl-life-core';

// Create options
const some = Option.some(42);
const none = Option.none<number>();

// From nullable
const opt = Option.fromNullable(maybeNull);

// Transform
const doubled = some.map(x => x * 2); // Some(84)

// Filter
const filtered = some.filter(x => x > 40); // Some(42)

// Chain
const result = some
  .map(x => x * 2)
  .flatMap(x => x > 50 ? Option.some(x) : Option.none());

// Safe unwrapping
const value = result.unwrapOr(0);

Error Handling

Specialized error classes with serialization support.

import {
  AppError,
  ValidationError,
  DatabaseError,
  AuthError,
  NetworkError,
} from '@gl-life/gl-life-core';

// Base error
throw new AppError('USER_NOT_FOUND', 'User does not exist', {
  userId: 123,
});

// Validation error
throw new ValidationError(
  'INVALID_EMAIL',
  'Email format is invalid',
  { field: 'email', value: 'bad-email', constraint: 'format' }
);

// Database error
throw new DatabaseError(
  'QUERY_FAILED',
  'Failed to execute query',
  { query: 'SELECT * FROM users', table: 'users' }
);

// Auth error
throw new AuthError(
  'TOKEN_EXPIRED',
  'Authentication token has expired',
  { userId: '123', tokenType: 'JWT', reason: 'expired' }
);

// Network error
throw new NetworkError(
  'REQUEST_FAILED',
  'HTTP request failed',
  { statusCode: 404, url: 'https://api.example.com', method: 'GET' }
);

// Serialization
const error = new ValidationError('ERROR_CODE', 'Message');
const json = error.toJSON();
const restored = AppError.fromJSON(json);

Logging

Structured JSON logging with context and levels.

import { Logger, LogLevel } from '@gl-life/gl-life-core';

// Create logger
const logger = new Logger({
  level: LogLevel.INFO,
  context: { service: 'api', version: '1.0.0' },
});

// Log at different levels
logger.debug('Debug message', { details: 'extra info' });
logger.info('User logged in', { userId: 123 });
logger.warn('Rate limit approaching', { requests: 950 });
logger.error('Database connection failed', { error: 'timeout' });

// Child logger with additional context
const requestLogger = logger.createChild({
  requestId: 'abc-123',
  method: 'GET',
  path: '/api/users',
});

requestLogger.info('Request received'); // Includes parent + child context

// Output format (JSON)
// {
//   "timestamp": "2024-01-01T12:00:00.000Z",
//   "level": "info",
//   "message": "Request received",
//   "service": "api",
//   "version": "1.0.0",
//   "requestId": "abc-123",
//   "method": "GET",
//   "path": "/api/users"
// }

Event Bus

Type-safe publish-subscribe event system.

import { EventBus } from '@gl-life/gl-life-core';

const eventBus = new EventBus();

// Subscribe to events
const unsubscribe = eventBus.subscribe('user:login', (data) => {
  console.log('User logged in:', data.userId);
});

// Wildcard subscriptions
eventBus.subscribe('*', (data) => {
  console.log('Any event:', data);
});

// Emit events (async with error collection)
const errors = await eventBus.emit('user:login', {
  userId: 123,
  timestamp: new Date(),
});

// Unsubscribe
unsubscribe();
// or
eventBus.unsubscribe('user:login', handler);

// Management
eventBus.listenerCount('user:login'); // Number of handlers
eventBus.eventNames(); // All event names
eventBus.clear(); // Remove all handlers
eventBus.clear('user:login'); // Remove handlers for specific event

Configuration

Configuration management with environment variables and Zod validation.

import { Config } from '@gl-life/gl-life-core';
import { z } from 'zod';

// Define schema
const schema = z.object({
  PORT: z.number().min(1).max(65535).default(3000),
  HOST: z.string().default('localhost'),
  DATABASE_URL: z.string().url(),
  DEBUG: z.boolean().default(false),
});

// Create config
const config = new Config({
  schema,
  envPrefix: 'APP_', // Loads from APP_PORT, APP_HOST, etc.
  defaults: { DEBUG: true }, // Override schema defaults
});

// Get values (type-safe with generics)
const port = config.get<number>('PORT'); // 3000 or from APP_PORT
const host = config.get('HOST', 'default-host'); // With fallback

// Set values (validated against schema)
config.set('PORT', 8080);

// Check existence
if (config.has('DATABASE_URL')) {
  // ...
}

// Get all config
const allConfig = config.getAll();

// Delete and clear
config.delete('PORT'); // Returns `this` for chaining
config.clear();

// Type conversion from environment
// APP_PORT=8080 → number
// APP_DEBUG=true → boolean
// APP_CONFIG='{"key":"value"}' → object

Utilities

Deep Clone

Clone objects with circular reference handling.

import { deepClone } from '@gl-life/gl-life-core';

const original = {
  date: new Date(),
  regex: /test/i,
  map: new Map([['key', 'value']]),
  set: new Set([1, 2, 3]),
  nested: { deep: { value: 42 } },
};

// Handle circular references
original.self = original;

const cloned = deepClone(original);
// cloned is a deep copy, cloned.self === cloned

Debounce

Delay function execution until after a wait period.

import { debounce } from '@gl-life/gl-life-core';

const search = debounce((query: string) => {
  console.log('Searching for:', query);
}, 300);

search('a');
search('ab');
search('abc'); // Only this will execute after 300ms

// Cancel pending execution
search.cancel();

Throttle

Limit function execution rate.

import { throttle } from '@gl-life/gl-life-core';

const onScroll = throttle(() => {
  console.log('Scroll event');
}, 100);

window.addEventListener('scroll', onScroll);
// Executes at most once per 100ms

Retry

Retry async operations with exponential backoff.

import { retry } from '@gl-life/gl-life-core';

const fetchData = async () => {
  const response = await fetch('https://api.example.com/data');
  if (!response.ok) throw new Error('Fetch failed');
  return response.json();
};

// Retry up to 3 times with exponential backoff
const data = await retry(fetchData, {
  maxAttempts: 3,
  delay: 1000, // 1s, 2s, 3s between attempts
});

Sleep

Promise-based delay.

import { sleep } from '@gl-life/gl-life-core';

async function process() {
  console.log('Start');
  await sleep(1000); // Wait 1 second
  console.log('After 1 second');
}

Validators

Email and URL validation.

import { isEmail, isURL } from '@gl-life/gl-life-core';

// Email validation (RFC 5322 compliant)
isEmail('[email protected]'); // true
isEmail('invalid@'); // false

// URL validation (http/https only)
isURL('https://example.com'); // true
isURL('ftp://example.com'); // false

API Reference

Types

  • Result<T, E> - Type-safe result type for operations that may fail
  • Option<T> - Type for optional values

Errors

  • AppError - Base error class with code and metadata
  • ValidationError - Validation failure errors
  • DatabaseError - Database operation errors
  • AuthError - Authentication/authorization errors
  • NetworkError - Network request errors

Services

  • Logger - Structured JSON logging with levels and context
  • EventBus - Publish-subscribe event system
  • Config - Configuration management with validation

Utilities

  • deepClone<T>(value: T): T - Deep clone with circular references
  • debounce<T>(fn: T, wait: number): DebouncedFunction<T> - Debounce function
  • throttle<T>(fn: T, wait: number): ThrottledFunction<T> - Throttle function
  • retry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T> - Retry with backoff
  • sleep(ms: number): Promise<void> - Async delay
  • isEmail(email: string): boolean - Email validator
  • isURL(url: string): boolean - URL validator

TypeScript Support

Full TypeScript support with comprehensive type definitions.

import type {
  Result,
  Option,
  AppErrorJSON,
  LoggerOptions,
  EventHandler,
  ConfigOptions,
  RetryOptions,
} from '@gl-life/gl-life-core';

Testing

The package includes comprehensive tests with high coverage:

npm test              # Run tests
npm run test:watch    # Watch mode
npm run test:coverage # Coverage report

Support

For questions, issues, or feature requests, please contact us at [email protected].

Visit gl.life for more information about GoodLife Sargam.

License

Apache-2.0 © GoodLife


Part of the GoodLife Sargam ecosystem

For more information, visit gl.life.