Skip to content

lokicoule-stack/emitter

Repository files navigation

Lokiverse Emitter

npm version License: MIT TypeScript codecov

TypeScript-first event emitter that doesn't make me question my life choices.

The Good Parts

TypeScript

import { createEmitter } from '@lokiverse/emitter'

type Events = {
  'meeting:endless': { minutesWasted: number }
  'meeting:scheduled': { conflictsWithLunch: boolean }
  'meeting:cancelled': { excuseQuality: number }
}

const emitter = createEmitter<Events>()

// Your IDE actually knows what's going on
emitter.meeting.$on('endless', ({ minutesWasted }) => {
  if (minutesWasted < 60) {
    console.log('That was just a warm-up')
  }
  if (minutesWasted > 120) {
    console.log('Time to update the resume')
  }
})

Features

  • 🎯 Actually Type-Safe: Because any is just admitting defeat
  • 🌳 Proper Namespacing: Not the "string prefix" kind of fake namespacing
  • 🃏 Wildcard Listeners: Like RegEx, but without the therapy sessions
  • 🚀 Zero Dependencies: No node_modules black hole
  • 🤏 Tiny Bundle: Smaller than your last code review comments

Installation

pnpm add @lokiverse/emitter

Usage

Basic Usage (That Actually Works)

// Define events (with real types, not "documentation")
type GitEvents = {
  'commit:push': { message: string; boringLevels: number }
  'commit:revert': { excuse: string }
}

const git = createEmitter<GitEvents>()

// Your IDE is now your friend
git.commit.$on('push', ({ message, boringLevels }) => {
  if (message.includes('fix typo')) {
    console.log('Sure it was "just" a typo')
  }
})

One-Time Events

// For those "it worked on my machine" moments
git.commit.$once('revert', ({ excuse }) => {
  console.log(`Saving ${excuse} for future use`)
})

Wildcard Magic

// Catch all the things related to commits
git.commit.$on('*', (event, data) => {
  console.log(`Git did something: ${event}`, data)
  // Perfect for those "what just happened?" moments
})

// Use wildcards with namespaces as flat as earth
git.$on('commit:*', (event, data) => {
  console.log(`Revert or commit? That is the question: ${event}`, data)
})

Namespace Like You Mean It

// Split your concerns (unlike your PRs)
const commitEvents = git.$ns('commit')
commitEvents.$on('push', handlePush) // Clean and tidy

Real World Examples (Because We All Copy-Paste)

Error Handling

type ErrorEvents = {
  'error:404': { url: string; lastSeenAlive: Date }
  'error:500': { stack: string; blame: string }
}

const emitter = createEmitter<ErrorEvents>()

emitter.error.$on('500', ({ stack, blame }) => {
  console.log(`Time to blame ${blame || 'the intern'}`)
})

Feature Flags

type FeatureEvents = {
  'feature:enabled': { name: string; whoToBlame: string }
  'feature:disabled': { name: string; excuses: string[] }
}

const emitter = createEmitter<FeatureEvents>()

emitter.feature.$on('enabled', ({ name, whoToBlame }) => {
  console.log(`${name} is now enabled. If it breaks, talk to ${whoToBlame}`)
})

Contributing

Found a bug? Open an issue. Have a fix? PR welcome.

Just remember: With great type safety comes great responsibility.

License

MIT © Lokiverse