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

@grlt-hub/app-compose

v2.0.3

Published

Compose modules into apps

Downloads

27

Readme

What is it?

app-compose is a library for module-based applications. It helps developers easily connect different parts of an application — features, entities, services, and so on — so they work together as a single system.

With app-compose, you can:

  • Simplify the management of complex dependencies.
  • Control the order in which modules run.
  • Intuitively enable or disable parts of the application.
  • Clearly visualize the parts of the application and their connections.

Instead of manually managing the chaos of modules, app-compose turns them into a well-organized and scalable application.

Cooking Up Your Application

An application is like a dish: a collection of features, entities, and services. But by themselves, they don’t make an application. To bring everything to life, you need to combine them properly: at the right time, in the right order, and without anything extra. One misstep, and instead of a pizza, you might end up with a cake.

If you’re unsure how to connect modules into a single system, app-compose can simplify the process for you.

Example

import { createContainer, compose } from '@grlt-hub/app-compose';

// Imagine we are cooking a dish in our restaurant kitchen.
// There are three steps:
// 1. hire the chef
// 2. order the ingredients,
// 3. and cook the pizza.

// First: prepare the "chef"
// it’s like hiring the chef to start cooking.
const chef = createContainer({
  // The name of our chef.
  id: 'John Doe',
  // This chef specializes in Italian cuisine.
  domain: 'italian-chef',
  start: async () => {
    // For example, we are hiring a chef.
    const hiredChef = await hireChef();

    // We return our chef.
    return { api: hiredChef };
  },
});

// Second: if the chef is hired,
// we need to order the ingredients.
const ingredients = createContainer({
  id: 'ingredients',
  domain: 'shop',
  // The ingredients ordering depends on the chef.
  dependencies: [chef],
  // If the chef is on break,
  // we can't proceed with the order.
  enable: (api) => api['John Doe'].hasBreak === false,
  start: async (api) => {
    // We order the ingredients.
    const orderedIngredients = await orderIngredients();

    // We return the ordered ingredients.
    return { api: { orderedIngredients } };
  },
});

// Third: we make the pizza.
const pizza = createContainer({
  id: 'pizza',
  domain: 'dish',
  dependencies: [chef, ingredients],
  start: (api) => {
    // The chef uses the ingredients
    // to make the pizza.
    const pepperoniPizza = api['John Doe'].makePizza({
      ingredients: api.ingredients.orderedIngredients,
    });

    // The pizza is ready!
    return { api: pepperoniPizza };
  },
});

// Now the stages: we split the process into steps.
// 1: "prepare" — hiring the chef and ordering the ingredients.
// 2: "cooking" — making the pizza.
const cmd = await compose({
  stages: [
    ['prepare', [chef, ingredients]],
    ['cooking', [pizza]],
  ],
  // We require everything to be ready.
  required: 'all',
});

// The cooking process has started!
await cmd.up();

Example Status Flow

Here’s how the statuses change during the cooking process:

  1. Initial state:
  • chef: 'idle', ingredients: 'idle' — Everything is waiting.
  • chef: 'pending', ingredients: 'idle' — The chef is on the way to the kitchen.
  1. If the chef is ready to work:
  • chef: 'done', ingredients: 'pending' — Ordering the ingredients.
  • chef: 'done', ingredients: 'done', pizza: 'idle' — All ingredients have been delivered.
  • chef: 'done', ingredients: 'done', pizza: 'pending' — Starting to make the pizza.
  • chef: 'done', ingredients: 'done', pizza: 'done' — The pizza is ready!
  1. If the chef is here, but taking a break:
  • chef: 'done', ingredients: 'off', pizza: 'off' — Cooking is canceled.

Strengths of the Library

  • Automatically resolves dependencies, removing the need to manually specify all containers.
  • Simplifies working with feature-toggles by eliminating excessive if/else logic for disabled functionality.
  • Allows you to define which parts of the application to run and in what order, prioritizing more important and less important dependencies.
  • Offers the ability to visualize the system composed of containers effectively (including transitive dependencies and their paths).
  • Provides a simple and intuitive developer experience (DX).
  • Ensures high performance, suitable for scalable applications.
  • Includes debugging tools to facilitate the development process.
  • Covered by 100% tests, including type tests.

What app-compose is NOT

  • It does not tell you how to build a module. You choose how your modules work. app-compose only helps you put them together in one app.
  • It does not manage data or state. If you need state (like Effector or Redux), you add it inside your modules. app-compose only starts them.

Documentation

Ready to get started? Check out the full documentation to dive deeper.

Community

Have questions or want to contribute? Join our community to connect with other developers.