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

@owlmeans/client-module

v0.1.1

Published

The `@owlmeans/client-module` package provides a client-side extension of the OwlMeans module system, specifically designed for frontend applications. It extends the core `@owlmeans/module` package with client-specific functionality including API calls, U

Downloads

18

Readme

OwlMeans Client Module

The @owlmeans/client-module package provides a client-side extension of the OwlMeans module system, specifically designed for frontend applications. It extends the core @owlmeans/module package with client-specific functionality including API calls, URL generation, and request validation.

Overview

The client module system builds upon the foundational module concepts from @owlmeans/module but adds client-specific capabilities:

  • API Calls: Automatically handle API requests to backend services
  • URL Generation: Generate URLs for client-side navigation
  • Request Validation: Validate requests before making API calls
  • Module Elevation: Transform basic modules into client modules with enhanced capabilities
  • Context Integration: Seamlessly integrate with client contexts for configuration and services

Key Concepts

ClientModule

A ClientModule extends the basic module concept with client-specific methods for making API calls and generating URLs. It maintains the same route, guard, and validation system as the base module while adding client-side functionality.

Module Elevation

The process of transforming a basic module into a client module with enhanced capabilities. This allows you to upgrade existing modules to support client-side operations.

API vs URL Calls

Client modules can operate in two modes:

  • API Mode: Makes actual HTTP requests to backend services
  • URL Mode: Generates URLs for client-side navigation and routing

Installation

npm install @owlmeans/client-module

Core API Reference

Types

ClientModule<T, R>

Main interface that extends CommonModule with client-specific functionality.

interface ClientModule<T = {}, R extends ClientRequest = ClientRequest> extends CommonModule {
  route: ClientRouteModel
  call: ModuleCall<T, R>
  validate: ModuleFilter<R>
  getPath: (partial?: boolean) => string
  request: (request?: Partial<R>) => R
}

Properties:

  • route: ClientRouteModel - Enhanced route model with client-specific features
  • call: ModuleCall<T, R> - Function to make API calls or generate URLs
  • validate: ModuleFilter - Function to validate requests
  • getPath: Function to get the module path (full or partial)
  • request: Function to create a request object for the module

ClientRequest

Extended request interface with client-specific properties.

interface ClientRequest<T extends {} = {}> extends AbstractRequest<T> {
  full?: boolean  // Whether to generate full URLs with domain
}

ClientModuleOptions

Configuration options for creating client modules.

interface ClientModuleOptions extends CommonModuleOptions {
  force?: boolean                    // Force module elevation even if already elevated
  routeOptions?: ClientRouteOptions  // Client-specific route options
  validateOnCall?: boolean           // Whether to validate requests before API calls
}

ModuleCall<T, R>

Function signature for making module calls.

interface ModuleCall<T, Req extends ClientRequest = ClientRequest> {
  <Type extends T, R extends Req = Req, P extends AbstractResponse<Type> = AbstractResponse<Type>>
  (req?: Partial<R>, res?: P): Promise<[Type, ModuleOutcome]>
}

ModuleFilter

Function signature for validating module requests.

interface ModuleFilter<Req extends AbstractRequest = AbstractRequest> {
  <R extends Req>(req?: Partial<R>): Promise<boolean>
}

Core Functions

module(route, handler?, opts?)

Creates a new client module instance.

function module<T, R extends AbstractRequest = AbstractRequest>(
  arg: CommonModule | ClientRouteModel | CommonRouteModel,
  handler?: RefedModuleHandler<T, R> | ClientModuleOptions | boolean,
  opts?: ClientModuleOptions | boolean
): ClientModule<T, R>

Parameters:

  • arg: Module source - can be an existing module, client route model, or common route model
  • handler: Optional handler function or options object
  • opts: Optional configuration options

Returns: ClientModule instance

Example:

import { module } from '@owlmeans/client-module'
import { route } from '@owlmeans/client-route'

// Create a client module for API calls
const userModule = module(route('users', '/api/users'))

// Create a client module with validation
const createUserModule = module(
  route('create-user', '/api/users', { method: 'POST' }),
  { validateOnCall: true }
)

// Create a client module with custom handler
const navigationModule = module(
  route('profile', '/profile'),
  ({ ref }) => async (req, res) => {
    // Custom handler logic
    const url = ref.getPath()
    res.resolve(url, ModuleOutcome.Ok)
  }
)

elevate(modules, alias, handler?, opts?)

Elevates an existing module to a client module with enhanced capabilities.

function elevate<T = {}, R extends AbstractRequest = AbstractRequest>(
  modules: (CommonModule | ClientModule<T, R>)[],
  alias: string,
  handler?: RefedModuleHandler<T, R> | ClientModuleOptions | boolean,
  opts?: ClientModuleOptions | boolean
): ClientModule<T, R>[]

Parameters:

  • modules: Array of modules to search and elevate
  • alias: Alias of the module to elevate
  • handler: Optional handler function or options
  • opts: Optional configuration options

Returns: Array of modules with the specified module elevated

Example:

import { elevate } from '@owlmeans/client-module'

const modules = [
  basicUserModule,
  basicProfileModule
]

// Elevate the user module to support API calls
const elevatedModules = elevate(modules, 'users', {
  validateOnCall: true
})

stab

A stub handler that returns undefined - useful for modules that don't need custom handling.

const stab: RefedModuleHandler<{}> = () => () => {
  return void 0 as any
}

Example:

const simpleModule = module(route('simple', '/simple'), stab)

provideRequest(alias, path)

Creates a basic request object for a module.

function provideRequest<T extends {} = {}>(alias: string, path: string): AbstractRequest<T>

Parameters:

  • alias: Module alias
  • path: Module path

Returns: Basic request object

Example:

const request = provideRequest('users', '/api/users')
request.query = { limit: 10 }

Module Methods

call(req?, res?)

Makes an API call or generates a URL depending on the module configuration.

const [result, outcome] = await userModule.call({
  params: { id: '123' },
  query: { include: 'profile' }
})

validate(req?)

Validates a request against the module's filter schema.

const isValid = await userModule.validate({
  params: { id: '123' },
  body: { name: 'John' }
})

getPath(partial?)

Gets the module path, optionally returning a partial path.

const fullPath = userModule.getPath()     // '/api/users/:id'
const partialPath = userModule.getPath(true)  // '/users/:id'

request(request?)

Creates a request object for the module with optional overrides.

const request = userModule.request({
  params: { id: '123' },
  query: { include: 'profile' }
})

Usage Examples

Basic API Module

import { module } from '@owlmeans/client-module'
import { route } from '@owlmeans/client-route'

// Create a module for fetching users
const usersModule = module(route('users', '/api/users'))

// Make an API call
const [users, outcome] = await usersModule.call({
  query: { limit: 10, page: 1 }
})

Module with Validation

import { module, filter, body } from '@owlmeans/client-module'
import { route } from '@owlmeans/client-route'

// Create a module with request validation
const createUserModule = module(
  route('create-user', '/api/users', { method: 'POST' }),
  {
    validateOnCall: true,
    filter: body({
      type: 'object',
      properties: {
        name: { type: 'string' },
        email: { type: 'string', format: 'email' }
      },
      required: ['name', 'email']
    })
  }
)

// This will validate the request before making the API call
const [user, outcome] = await createUserModule.call({
  body: {
    name: 'John Doe',
    email: '[email protected]'
  }
})

Navigation Module

import { module } from '@owlmeans/client-module'
import { route } from '@owlmeans/client-route'

// Create a module for client-side navigation
const profileModule = module(
  route('profile', '/profile/:id'),
  ({ ref }) => async (req, res) => {
    const url = ref.getPath()
    // Custom navigation logic
    window.history.pushState({}, '', url)
    res.resolve(url, ModuleOutcome.Ok)
  }
)

// Generate URL and navigate
const [url, outcome] = await profileModule.call({
  params: { id: '123' }
})

Module Elevation

import { elevate } from '@owlmeans/client-module'
import { basicModules } from './basic-modules'

// Elevate multiple modules for client-side use
const clientModules = [
  ...elevate(basicModules, 'users', { validateOnCall: true }),
  ...elevate(basicModules, 'posts', { validateOnCall: false })
]

Complex Module with Guards and Gates

import { module, guard, gate } from '@owlmeans/client-module'
import { route } from '@owlmeans/client-route'

// Create a protected module
const adminModule = module(
  route('admin-users', '/api/admin/users'),
  {
    guards: ['authenticated', 'admin'],
    gate: 'admin-access',
    gateParams: ['resource'],
    validateOnCall: true
  }
)

// The module will automatically check authentication and authorization
const [users, outcome] = await adminModule.call()

Integration Patterns

With React Components

import { useEffect, useState } from 'react'
import { userModule } from './modules'

function UserProfile({ userId }) {
  const [user, setUser] = useState(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const fetchUser = async () => {
      try {
        const [userData, outcome] = await userModule.call({
          params: { id: userId }
        })
        setUser(userData)
      } catch (error) {
        console.error('Failed to fetch user:', error)
      } finally {
        setLoading(false)
      }
    }

    fetchUser()
  }, [userId])

  if (loading) return <div>Loading...</div>
  return <div>{user?.name}</div>
}

With Context Configuration

import { createContext } from '@owlmeans/client-context'
import { module } from '@owlmeans/client-module'

// Create context with API configuration
const context = createContext({
  webService: {
    default: 'api-service',
    users: 'user-service'
  }
})

// Create module with context
const userModule = module(route('users', '/api/users'))
userModule.ctx = context

// The module will use the configured API service
const [users, outcome] = await userModule.call()

Error Handling

import { ClientValidationError } from '@owlmeans/client-module'

try {
  await userModule.validate({
    body: { invalidData: true }
  })
} catch (error) {
  if (error instanceof ClientValidationError) {
    console.error('Validation failed:', error.message)
  } else {
    console.error('Unexpected error:', error)
  }
}

Error Types

ClientModuleError

Base error class for client module errors.

class ClientModuleError extends ResilientError {
  constructor(message: string)
}

ClientValidationError

Thrown when request validation fails.

class ClientValidationError extends ClientModuleError {
  constructor(message: string)
}

Best Practices

  1. Use Validation: Enable validateOnCall for modules that accept user input
  2. Handle Errors: Always wrap API calls in try-catch blocks
  3. Modular Design: Create separate modules for different API endpoints
  4. Context Integration: Use contexts to configure API services and authentication
  5. Type Safety: Provide generic types for request/response data
  6. Route Reuse: Elevate existing basic modules rather than creating new ones when possible

Dependencies

This package depends on:

  • @owlmeans/module - Core module system
  • @owlmeans/client-route - Client-side routing
  • @owlmeans/client-context - Client context management
  • @owlmeans/client-config - Client configuration
  • @owlmeans/api - API client functionality
  • ajv - JSON schema validation

Related Packages