Forest Logo
search
package_2

compose

By @paramacode

Roblox

Mirrored

Compose

A deterministic, scope-aware, capability-based composition core for Luau frameworks.

Compose is not a framework and does not prescribe gameplay patterns, ECS, or architecture styles. It is a low-level composition and dependency core designed to be the stable foundation for multiple frameworks and large Roblox codebases.

It focuses on explicit dependencies, runtime enforcement, and structural safety, rather than convenience or magic.


Why Compose exists

Most Roblox projects fail architecturally for the same reasons:

  • Implicit dependencies
  • Global state access
  • Weak separation between Client / Server / Shared
  • No enforcement of module boundaries
  • Systems that work… until they scale

Compose exists to solve these problems once, at the foundation level.


Core principles

1. Deterministic composition

  • Modules are composed in a known, explicit order
  • No auto-discovery
  • No hidden lifecycle hooks
  • No reflection or magic

If something runs, it is because you explicitly declared it.


2. Capability-based dependency access

Modules cannot access dependencies implicitly.

Each module must declare:

  • What it depends on (Requires)
  • What scope it runs in (Scope)

At runtime, each module receives a restricted context that only allows access to its declared dependencies.

Attempting to access anything else fails immediately.


3. Scope enforcement (Client / Server / Shared)

Dependencies and modules declare their scope explicitly:

  • Client
  • Server
  • Shared

Invalid combinations are rejected during composition.

This prevents:

  • Client code accessing server-only systems
  • Accidental cross-boundary coupling
  • Silent security issues

4. No OOP required

Compose is built around functional composition, not classes.

  • No inheritance
  • No base classes
  • No metatable hierarchies

Modules are plain tables with optional lifecycle functions.


Basic example

local Compose = require(ReplicatedStorage.Compose)

local LoggerToken = {}

local application = Compose.Define({
    Scope = 'Server',

    Dependencies = {
        [LoggerToken] = {
            Scope = 'Shared',

            Value = {
                log = function(message)
                    print(message)
                end
            }
        }
    },

    Modules = {
        {
            Scope = 'Shared',
            Requires = {LoggerToken},

            Create = function(context)
                local logger = context.Resolve(LoggerToken)

                return {
                    Initiate = function()
                        logger.log('Hello from compose')
                    end
                }
            end
        }
    }
})

application.Initiate()

Lifecycle

Modules may optionally implement any of the following functions:

  • Initiate()
  • Execute()
  • Terminate()

Only the functions that exist are called.

There are no implicit defaults.


What Compose deliberately does NOT do

  • ❌ Automatic module discovery
  • ❌ Global service locators
  • ❌ Reflection-based wiring
  • ❌ Silent dependency injection
  • ❌ Runtime guessing

If you want convenience over correctness, this is not the right tool.


Intended audience

Compose is designed primarily for:

  • Developers building multiple internal frameworks
  • Large or long-lived Roblox projects
  • Codebases where architectural drift is a real cost

It is opinionated by design.


Status

Compose is stable for internal framework use.

The API is intentionally small and unlikely to change frequently, but semantic versioning is respected.


License

MIT

Package Details

Install command (Click to copy)


Version

0.1.1

License

MIT

check_circle

Safe for commercial use

Automated license review — not legal advice.