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

@owlmeans/context

v0.1.1

Published

The **@owlmeans/context** package provides dependency management for OwlMeans Common libraries, specifically designed for fullstack microservices and microclients development.

Readme

@owlmeans/context

The @owlmeans/context package provides dependency management for OwlMeans Common libraries, specifically designed for fullstack microservices and microclients development.

Purpose

This package serves as a foundational dependency injection and management system that enables:

  • Service Registration and Resolution: Register and access services across different application layers
  • Module Management: Handle URL units that declare routes and nesting for both frontend and backend
  • Resource Management: Manage data sources and external resources with proper initialization
  • Middleware System: Apply cross-cutting concerns at different stages of the application lifecycle
  • Multi-layer Architecture: Support hierarchical layers (System, Global, Service, Entity, User) for complex applications

Key Concepts

Context

A context acts as an application instance that manages the lifecycle and dependencies of services, modules, and resources. Multiple contexts can exist within one application with different capabilities.

Layers

The package supports a hierarchical layer system:

  • System: System-wide components
  • Global: Global application components
  • Service: Service-specific components
  • Entity: Entity-specific components
  • User: User-specific components

Modules

In the context of OwlMeans Common libraries, a "module" is not a programmatic module but a URL unit in the system. Modules allow you to:

  • Declare URLs and nesting structure
  • Transform URLs to routes and attach handlers on the backend
  • Specify which components to render on the frontend
  • Generate final URLs for navigation or API calls
  • Maintain a single source of truth for all possible routes

Services

Services are components that provide functionality and can be initialized either immediately or lazily.

Resources

Resources are components that provide data or external functionality and can be initialized when needed.

Middlewares

Middlewares are components that can be applied at different stages of the context lifecycle to provide cross-cutting functionality.

API Reference

Factory Functions

The package uses factory functions instead of constructors for object creation:

makeBasicContext<C extends BasicConfig>(cfg: C): BasicContext<C>

Creates a basic context instance.

import { makeBasicContext, makeBasicConfig, AppType } from '@owlmeans/context'

const config = makeBasicConfig(AppType.Backend, 'my-service')
const context = makeBasicContext(config)

makeBasicConfig<C extends BasicConfig>(type: AppType, service: string, cfg?: Partial<C>): C

Creates a basic configuration object.

Parameters:

  • type: Application type (Frontend or Backend)
  • service: Service name
  • cfg: Additional configuration options
import { makeBasicConfig, AppType, Layer } from '@owlmeans/context'

const config = makeBasicConfig(AppType.Frontend, 'web-client', {
  layer: Layer.Service,
  debug: { all: true }
})

createService<S extends InitializedService>(alias: string, service: Partial<S>, init?: InitMethod<S>): S

Creates a service that initializes immediately.

import { createService } from '@owlmeans/context'

const myService = createService('my-service', {
  // service implementation
}, (service) => async () => {
  // initialization logic
  console.log('Service initialized')
  service.initialized = true
})

createLazyService<S extends LazyService>(alias: string, service: Partial<S>, init?: InitMethod<S>): S

Creates a service that initializes only when first accessed.

import { createLazyService } from '@owlmeans/context'

const lazyService = createLazyService('lazy-service', {
  // service implementation
}, (service) => async () => {
  // lazy initialization logic
  console.log('Lazy service initialized')
  service.initialized = true
})

appendContextual<T extends Contextual>(alias: string, contextual: Partial<T>): T

Helps make objects contextual by adding context management capabilities.

import { appendContextual } from '@owlmeans/context'

const contextualObject = appendContextual('my-object', {
  // object implementation
})

Core Interfaces

BasicContext<C extends BasicConfig>

The main context interface that provides comprehensive dependency management. Each method serves a specific purpose in the context lifecycle and dependency resolution:

interface BasicContext<C extends BasicConfig> {
  cfg: C
  stage: ContextStage
  
  // Lifecycle methods
  waitForConfigured(): Promise<boolean>
  waitForInitialized(): Promise<boolean>
  configure<T extends BasicContext<C>>(): T
  init<T extends BasicContext<C>>(): Promise<T>
  
  // Registration methods
  registerService<T extends BasicContext<C>>(service: Service): T
  registerModule<T extends BasicContext<C>>(module: BasicModule): T
  registerModules<T extends BasicContext<C>>(modules: BasicModule[]): T
  registerResource<T extends BasicContext<C>>(resource: BasicResource): T
  registerMiddleware<T extends BasicContext<C>>(middleware: Middleware): T
  
  // Access methods
  service<T extends Service>(alias: string): T
  module<T extends BasicModule>(alias: string): T
  resource<T extends BasicResource>(alias: string): T
  modules<T extends BasicModule>(): T[]
  
  // Utility methods
  hasResource(alias: string): boolean
  hasService(alias: string): boolean
  
  get config(): Promise<C>
}

Context Methods Detailed Reference

Lifecycle Methods

waitForConfigured(): Promise<boolean>

  • Purpose: Returns a promise that resolves when the context has completed its configuration stage
  • Usage: Useful for waiting for configuration to complete before proceeding
  • Returns: Promise that resolves to true when configuration is complete

waitForInitialized(): Promise<boolean>

  • Purpose: Returns a promise that resolves when the context has completed initialization and reached the Ready stage
  • Usage: Essential for ensuring all services and resources are initialized before use
  • Returns: Promise that resolves to true when initialization is complete

configure<T extends BasicContext<C>>(): T

  • Purpose: Transitions the context from Configuration stage to Loading stage
  • Behavior: Applies configuration middlewares and prepares the context for initialization
  • Usage: Must be called after registering all components and before init()
  • Returns: The context instance for method chaining

init<T extends BasicContext<C>>(): Promise<T>

  • Purpose: Initializes all registered services and resources, transitioning context to Ready stage
  • Behavior:
    • Executes init() methods on all registered services
    • Initializes all resources according to their layer availability
    • Applies loading and ready stage middlewares
    • Marks context as ready for use
  • Usage: Must be called after configure() to make the context operational
  • Returns: Promise that resolves to the initialized context instance

Registration Methods

registerService<T extends BasicContext<C>>(service: Service): T

  • Purpose: Registers a service with the context for dependency injection
  • Behavior:
    • Associates the service with the current context
    • Stores the service in the appropriate layer
    • Makes the service available for retrieval via service()
  • Usage: Call during configuration stage to register services
  • Returns: The context instance for method chaining

registerModule<T extends BasicContext<C>>(module: BasicModule): T

  • Purpose: Registers a module (URL unit) with the context
  • Behavior:
    • Associates the module with the current context
    • Makes the module available for route resolution and navigation
  • Usage: Register modules that define URL structures and routing
  • Returns: The context instance for method chaining

registerModules<T extends BasicContext<C>>(modules: BasicModule[]): T

  • Purpose: Convenience method to register multiple modules at once
  • Behavior: Iterates through the array and registers each module
  • Usage: Efficient way to register multiple modules simultaneously
  • Returns: The context instance for method chaining

registerResource<T extends BasicContext<C>>(resource: BasicResource): T

  • Purpose: Registers a resource (data source or external service) with the context
  • Behavior:
    • Associates the resource with the current context
    • Resources are initialized during context initialization based on layer availability
  • Usage: Register resources that provide data or external functionality
  • Returns: The context instance for method chaining

registerMiddleware<T extends BasicContext<C>>(middleware: Middleware): T

  • Purpose: Registers middleware for cross-cutting concerns during context lifecycle
  • Behavior:
    • Middleware is applied at specific stages (Configuration, Loading, Ready, Switching)
    • Multiple middlewares can be registered for the same stage
  • Usage: Register middleware for logging, validation, or other cross-cutting functionality
  • Returns: The context instance for method chaining

Access Methods

service<T extends Service>(alias: string): T

  • Purpose: Retrieves a registered service by its alias
  • Behavior:
    • Looks up the service in the current layer and falls back to Global layer
    • Handles lazy initialization if the service is not yet initialized
    • Throws SyntaxError if service is not found or not initialized
  • Usage: Primary way to access services for dependency injection
  • Returns: The requested service instance
  • Throws: SyntaxError if service not found or not initialized

module<T extends BasicModule>(alias: string): T

  • Purpose: Retrieves a registered module by its alias
  • Behavior:
    • Looks up the module in the current layer
    • Throws SyntaxError if module is not found
  • Usage: Access modules for route resolution and navigation
  • Returns: The requested module instance
  • Throws: SyntaxError if module not found

resource<T extends BasicResource>(alias: string): T

  • Purpose: Retrieves a registered resource by its alias
  • Behavior:
    • Looks up the resource in the current layer
    • Throws SyntaxError if resource is not found
  • Usage: Access resources for data operations or external service calls
  • Returns: The requested resource instance
  • Throws: SyntaxError if resource not found

modules<T extends BasicModule>(): T[]

  • Purpose: Retrieves all registered modules as an array
  • Behavior: Returns all modules registered in the current layer
  • Usage: Useful for iterating over all available modules
  • Returns: Array of all registered modules

Utility Methods

hasResource(alias: string): boolean

  • Purpose: Checks if a resource with the given alias exists
  • Behavior: Searches across all layers for the resource
  • Usage: Defensive programming to check resource availability before access
  • Returns: true if resource exists, false otherwise

hasService(alias: string): boolean

  • Purpose: Checks if a service with the given alias exists
  • Behavior: Searches across all layers for the service
  • Usage: Defensive programming to check service availability before access
  • Returns: true if service exists, false otherwise

Configuration Access

get config(): Promise<C>

  • Purpose: Provides access to the context configuration after it's been configured
  • Behavior: Returns a promise that resolves to the configuration object once context is configured
  • Usage: Access configuration settings after context setup
  • Returns: Promise that resolves to the configuration object

Properties

cfg: C

  • Purpose: Direct access to the context configuration object
  • Usage: Access configuration settings synchronously
  • Type: The configuration object of type C extends BasicConfig

stage: ContextStage

  • Purpose: Indicates the current lifecycle stage of the context
  • Values: Configuration, Loading, or Ready
  • Usage: Check context readiness before performing operations

BasicConfig

Configuration interface for contexts:

interface BasicConfig {
  ready: boolean
  service: string
  alias?: string
  layer: Layer
  type: AppType
  layerId?: string
  services?: Record<string, Object>
  debug?: {
    all?: boolean
    [section: string]: boolean | undefined
  }
}

Service

Interface for services:

interface Service extends Contextual {
  layers?: Layer[]
  initialized: boolean
  init?: () => Promise<void>
  lazyInit?: () => Promise<void>
  ready?: () => Promise<boolean>
}

BasicModule

Interface for modules:

interface BasicModule extends Contextual {
  _module: true
}

BasicResource

Interface for resources:

interface BasicResource extends Contextual {
  layers?: Layer[]
  init?: () => Promise<void>
}

Middleware

Interface for middlewares:

interface Middleware {
  type: MiddlewareType
  stage: MiddlewareStage
  apply: <C extends BasicConfig, T extends BasicContext<C>>(
    context: T, 
    args?: Record<string, string | undefined>
  ) => Promise<void>
}

Enums

Layer

enum Layer {
  System = 'system',
  Global = 'global',
  Service = 'service',
  Entity = 'entity',
  User = 'user'
}

AppType

enum AppType {
  Backend = 'backend',
  Frontend = 'frontend'
}

ContextStage

enum ContextStage {
  Configuration = 'configuration',
  Loading = 'loading',
  Ready = 'ready'
}

MiddlewareType

enum MiddlewareType {
  Config = 'config',
  Context = 'context'
}

MiddlewareStage

enum MiddlewareStage {
  Configuration = 'configuration',
  Loading = 'loading',
  Ready = 'ready',
  Switching = 'switching'
}

Usage Examples

Basic Usage

import { 
  makeBasicContext, 
  makeBasicConfig, 
  createService, 
  AppType, 
  Layer 
} from '@owlmeans/context'

// Create configuration
const config = makeBasicConfig(AppType.Backend, 'my-app', {
  layer: Layer.System,
  debug: { all: true }
})

// Create context
const context = makeBasicContext(config)

// Create and register a service
const myService = createService('database', {
  connect: () => console.log('Connected to database')
}, (service) => async () => {
  // Initialize the service
  service.connect()
  service.initialized = true
})

context.registerService(myService)

// Configure and initialize context
const configuredContext = context.configure()
await configuredContext.init()

// Use the service
const dbService = context.service('database')

Advanced Context Method Usage

import { 
  makeBasicContext, 
  makeBasicConfig, 
  createService, 
  createLazyService,
  AppType, 
  Layer,
  ContextStage 
} from '@owlmeans/context'

const config = makeBasicConfig(AppType.Backend, 'advanced-app')
const context = makeBasicContext(config)

// Register multiple services
const cacheService = createService('cache', {
  get: (key: string) => `cached-${key}`,
  set: (key: string, value: any) => console.log(`Set ${key}=${value}`)
})

const logService = createLazyService('logger', {
  log: (message: string) => console.log(`[LOG] ${message}`)
}, (service) => async () => {
  console.log('Logger initialized lazily')
  service.initialized = true
})

context.registerService(cacheService)
context.registerService(logService)

// Check service availability before use
if (context.hasService('cache')) {
  console.log('Cache service is available')
}

// Wait for specific lifecycle stages
await context.waitForConfigured()
console.log('Context configured')

// Configure and initialize
context.configure()
await context.init()

// Check current stage
console.log('Current stage:', context.stage) // ContextStage.Ready

// Access configuration after initialization
const finalConfig = await context.config
console.log('Final config:', finalConfig.service)

// Service access - cache service is already initialized
const cache = context.service('cache')
cache.set('key1', 'value1')

// Lazy service access - will initialize on first access
const logger = context.service('logger') // Triggers lazy initialization
logger.log('Application ready')

Method Chaining and Error Handling

import { 
  makeBasicContext, 
  makeBasicConfig, 
  createService, 
  appendContextual,
  AppType 
} from '@owlmeans/context'

const config = makeBasicConfig(AppType.Backend, 'chaining-example')
const context = makeBasicContext(config)

// Method chaining for registration
const service1 = createService('service1', { value: 1 })
const service2 = createService('service2', { value: 2 })
const module1 = appendContextual('module1', { _module: true, routes: {} })
const resource1 = appendContextual('resource1', { data: 'test' })

// Chain multiple registrations
context
  .registerService(service1)
  .registerService(service2)
  .registerModule(module1)
  .registerResource(resource1)

// Error handling for service access
try {
  const nonExistentService = context.service('non-existent')
} catch (error) {
  console.error('Service not found:', error.message)
  // Output: Service non-existent not found in layer service
}

// Safe service access using hasService
if (context.hasService('service1')) {
  const service = context.service('service1')
  console.log('Service value:', service.value)
}

// Error handling for uninitialized services
await context.configure().init()

// Now services are accessible
const service = context.service('service1')
console.log('Service accessible after init:', service.value)

Context Lifecycle Management

const context = makeBasicContext(config)

// Register components during Configuration stage
console.log('Stage:', context.stage) // ContextStage.Configuration

context.registerService(myService)
context.registerModule(myModule)

// Move to Loading stage
context.configure()
console.log('Stage:', context.stage) // ContextStage.Loading

// Move to Ready stage
await context.init()
console.log('Stage:', context.stage) // ContextStage.Ready

// Context lifecycle promises
const configuredPromise = context.waitForConfigured()
const initializedPromise = context.waitForInitialized()

// Both promises resolve immediately if context is already ready
await configuredPromise // Resolves to true
await initializedPromise // Resolves to true

Module Registration

import { appendContextual } from '@owlmeans/context'

// Create a module
const userModule = appendContextual('user', {
  _module: true,
  routes: {
    login: '/login',
    profile: '/profile'
  }
})

// Register the module
context.registerModule(userModule)

// Access the module
const module = context.module('user')

Resource Management

const dbResource = appendContextual('db-connection', {
  connection: null,
  init: async () => {
    // Initialize database connection
    console.log('Database connection initialized')
  }
})

context.registerResource(dbResource)

// Resource will be initialized during context initialization
await context.init()

// Access the resource
const db = context.resource('db-connection')

Middleware Usage

const loggingMiddleware = {
  type: MiddlewareType.Context,
  stage: MiddlewareStage.Ready,
  apply: async (context) => {
    console.log(`Context ${context.cfg.service} is ready`)
  }
}

context.registerMiddleware(loggingMiddleware)

Context Lifecycle

  1. Configuration Stage: Register services, modules, resources, and middlewares
  2. Loading Stage: Initialize services and resources
  3. Ready Stage: Context is ready for use
// Configuration stage
const context = makeBasicContext(config)
context.registerService(myService)
context.registerModule(myModule)

// Move to loading stage
context.configure()

// Initialize and move to ready stage
await context.init()

// Context is now ready
console.log(context.stage) // ContextStage.Ready

Integration with Other Packages

The context package integrates seamlessly with other OwlMeans packages:

import { makeServerContext } from '@owlmeans/server-context'
import { makeClientContext } from '@owlmeans/client-context'

// Server-side context with additional capabilities
const serverContext = makeServerContext(serverConfig)

// Client-side context with additional capabilities  
const clientContext = makeClientContext(clientConfig)

Helper Functions

assertContext<C extends BasicConfig, T extends BasicContext<C>>(ctx: T | undefined, location?: string): T

Asserts that a context is defined and throws an error if not.

import { assertContext } from '@owlmeans/context'

const context = assertContext(maybeContext, 'MyService')

isContextWithoutIds<C extends BasicConfig, T extends BasicContext<C>>(context: T): boolean

Checks if a context operates without IDs (System, Global, or Service layers).

import { isContextWithoutIds } from '@owlmeans/context'

const needsIds = !isContextWithoutIds(context)

Error Handling

The package throws SyntaxError for common issues:

  • Service not found: When accessing an unregistered service
  • Module not found: When accessing an unregistered module
  • Resource not found: When accessing an unregistered resource
  • Context not found: When context is undefined in a contextual object
  • Service not initialized: When accessing a non-initialized service

Best Practices

  1. Use Factory Functions: Always use the provided factory functions instead of constructors
  2. Layer Organization: Organize your components by appropriate layers
  3. Service Initialization: Choose between immediate and lazy initialization based on your needs
  4. Error Handling: Always handle potential errors when accessing services, modules, or resources
  5. Context Lifecycle: Respect the context lifecycle stages
  6. Middleware Order: Be mindful of middleware execution order and stages

TypeScript Support

The package is written in TypeScript and provides full type safety:

import type { BasicContext, BasicConfig, Service } from '@owlmeans/context'

interface MyConfig extends BasicConfig {
  customOption: string
}

interface MyService extends Service {
  customMethod(): void
}

const context: BasicContext<MyConfig> = makeBasicContext(config)
const service: MyService = context.service('my-service')