What Is the Model Factory in @maka/runtime? Purpose and Implementation
The model-factory module in @maka/runtime is the core instantiation utility that transforms static model definitions into live, runtime-aware objects for Apache Maka components, injecting dependencies like the store and eventBus while supporting custom factory registration and test mocking.
The model-factory module serves as the instantiation engine for the Apache Maka framework's component state layer. Located at packages/runtime/src/model-factory.ts, this utility ensures every component receives a correctly initialized model instance with consistent shape and fully wired dependencies.
Core Responsibilities of the Model Factory
The factory handles five critical concerns during the component lifecycle.
1. Instantiate Models from Schema Definitions
At its foundation, the factory constructs fresh model instances based on a component’s model definition—the JSON-like schema that declares state properties and their default values. When createModel() is invoked, the factory parses this definition and returns a reactive object ready for use inside view functions.
2. Inject Runtime Context
During creation, the factory automatically injects the current runtime context into the model instance. This context includes the store, eventBus, actionCreator, and any user-provided services registered with the application. By centralizing this wiring, the factory ensures every model can interact with the broader Maka application state and event system without manual configuration.
3. Apply Default Values and Type Coercion
The factory processes the model schema to apply declared defaults and coerce values to expected types. This guarantees that every component starts with a predictable state shape, preventing undefined reference errors and maintaining consistency across the component tree.
4. Support Custom Factory Registration
Developers can register specialized factories for specific model types using registerModelFactory(). When createModel() executes, the factory checks for a custom registration and delegates instantiation to the custom logic when present. This allows teams to extend base model behavior with cross-cutting concerns like logging, validation, or telemetry without modifying individual component definitions.
5. Enable Testing and Mocking
By centralizing model creation through a single entry point, the factory makes unit testing straightforward. Test suites can call setModelFactory() to replace the default implementation with a mock version that returns frozen plain objects or spies, isolating components from the full runtime stack.
Basic Usage: Creating a Model Instance
The createModel() function is the primary entry point for component authors. It accepts a model definition and returns a fully initialized instance.
import { createModel } from '@maka/runtime';
// Component-specific model definition
const myComponentModel = {
name: 'myComponent',
state: {
count: 0,
label: 'Hello',
},
};
// Runtime context is automatically supplied by the Maka runtime
const modelInstance = createModel(myComponentModel);
// Access reactive state inside a view
console.log(modelInstance.state.count); // → 0
In packages/runtime/src/model-factory.ts, the createModel() implementation handles the lookup for custom factories before falling back to default instantiation logic.
Extending Behavior with Custom Factories
For applications requiring specialized model behavior, the factory exposes a registration API.
import { registerModelFactory, createModel } from '@maka/runtime';
// Register a custom factory that adds logging capabilities
registerModelFactory('default', (definition, context) => {
const baseModel = context.defaultFactory(definition, context);
return {
...baseModel,
log(message: string) {
console.log(`[${definition.name}] ${message}`);
},
};
});
const myModel = createModel({
name: 'demo',
state: { value: 42 },
});
myModel.log('model created'); // Prints: [demo] model created
The registration system is implemented in packages/runtime/src/model-factory.ts and supports multiple factory types, allowing different instantiation strategies for different component categories.
Testing and Mocking Strategies
The factory’s centralized design simplifies test isolation by allowing complete replacement of the creation logic.
import { createModel, setModelFactory } from '@maka/runtime';
// Install a mock factory for unit tests
setModelFactory(() => ({
state: { count: 5 },
setState: jest.fn(),
}));
const testModel = createModel({ name: 'test', state: { count: 0 } });
expect(testModel.state.count).toBe(5);
expect(testModel.setState).not.toHaveBeenCalled();
This pattern is verified in packages/runtime/src/__tests__/model-factory-thinking.test.ts and packages/runtime/src/__tests__/model-factory-tool-call-index.test.ts, which cover both default instantiation paths and custom factory delegation.
Implementation Details and Source Structure
The core logic resides in packages/runtime/src/model-factory.ts, which exports the primary creation functions and the registration registry. The test suite at packages/runtime/src/__tests__/model-factory-thinking.test.ts validates typical runtime scenarios, while packages/runtime/src/__tests__/model-factory-tool-call-index.test.ts covers edge cases in custom factory registration and error handling.
Summary
- Centralized Instantiation: The
model-factoryin@maka/runtimetransforms static model definitions into live, reactive objects atpackages/runtime/src/model-factory.ts. - Dependency Injection: It automatically injects runtime services including
store,eventBus, andactionCreatorinto every new model. - Schema Enforcement: The factory applies default values and type coercion based on the component's model definition schema.
- Extensibility: Use
registerModelFactory()to inject custom creation logic for specific model types without modifying core framework code. - Testability: Call
setModelFactory()in test suites to replace the default implementation with mocks, enabling isolated component testing.
Frequently Asked Questions
How does the model factory handle runtime context injection?
The factory receives the current runtime context—containing the store, eventBus, actionCreator, and user services—as an internal parameter during the instantiation call. It merges these dependencies into the returned model object, ensuring every component has immediate access to the application’s state management and event system without manual wiring.
Can I override the model factory for specific components only?
Yes. When calling registerModelFactory(), you can specify a factory key that corresponds to specific model definition types. When createModel() executes, it checks the definition’s type identifier and delegates to the registered custom factory only when a matching key exists, falling back to the default implementation for all other components.
What is the difference between registerModelFactory() and setModelFactory()?
registerModelFactory() adds a factory to an internal registry keyed by type, allowing multiple specialized factories to coexist for different model categories. setModelFactory() replaces the global default factory entirely, which is primarily useful in testing scenarios where you want to intercept all model creation calls within a test suite.
Where are the model factory tests located in the Apache Maka repository?
The primary test coverage resides in packages/runtime/src/__tests__/model-factory-thinking.test.ts, which exercises standard instantiation and context injection. Additional edge-case coverage for custom registration logic is found in packages/runtime/src/__tests__/model-factory-tool-call-index.test.ts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →