@bigbyte/core
v0.8.2
Published
<div align="center">
Downloads
16
Readme
🔄️ @bigbyte/core - Core Decorators & Dependency Injection
Foundational decorators (@App, @Component, @Service, @Inject, @Value) and orchestration runtime for the BigByte ecosystem: typed component registry, event-driven bootstrap lifecycle and contextual value resolution.
📋 Table of Contents
- Features
- Installation
- Commands
- Decorators
- Basic Usage
- Detailed API
- Architecture
- Error Handling
- Advanced Examples
- License
✨ Features
- High-level decorators: @App, @Component, @Service for declarative registration.
- Type-based dependency injection via @Inject.
- External value injection (dynamic context) with @Value(key).
- Order and uniqueness control for decorators (automatic validations).
- Centralized registry in
componentRegistry(@bigbyte/ioc). - Bootstrap cycle orchestrated by an event bus (@bigbyte/events) with phases (declaration, execution, instantiation).
- Integration with
reflect-metadatato extract constructor / property types. - Categorized components (MAIN, COMPONENT, SERVICE) for clear graph semantics.
- Lazy and safe resolution: explicit error if the injected component does not exist.
- Integration with value context (
ctxStorefrom @bigbyte/ctx) for configuration / constants. - Ready for watch / reload environments (chokidar in @bigbyte/cli).
🚀 Installation
npm install @bigbyte/core🖥️ Commands
This package does not expose its own CLI commands. Its functionality is activated declaratively by importing the decorators within your application code.
For scaffolding / execution operations use the @bigbyte/cli package (if present in the project).
🤖 Decorators
List and main purpose:
- @App() Marks the main (root) application class. Must be the first decorator applied on that class. Triggers the final phase that instantiates the graph once all decorators have been processed.
- @Component(options?) Registers a class as a generic component (type COMPONENT). Allows additional container options (scope, alias, etc. if supported by @bigbyte/ioc).
- @Service() Semantic shortcut for business logic components (type SERVICE). Does not accept options in this version.
- @Inject() Property decorator. Injects the instance of a registered component whose type matches the decorated property's type.
- @Value(key) Property decorator. Injects an immutable value dynamically resolved from
ctxStoreby its key.
Order / Rules:
- @App only once and only on the root class.
- @Component and @Service are mutually exclusive (do not combine them on the same class nor with other component-type decorators).
- @Inject and @Value cannot be applied to private properties using the
#syntax. - The registry is materialized after the decorator execution chain finishes (event 'last').
🔧 Basic Usage
Minimal application example:
import 'reflect-metadata';
import { App, Service, Inject, Value, Component } from '@bigbyte/core';
@Service()
class TimeService {
now() { return new Date().toISOString(); }
}
@Component({ injectable: false })
class Printer {
print(msg: string) { console.log('[PRINT]', msg); }
}
@App()
class MainApp {
@Inject() private printer?: Printer; // Undefined value until resolved lazily
@Value('app.name') private appName!: string;
// Automatic constructor dependency injection
run(private timeService: TimeService) {
this.printer?.print(`${this.appName} started @ ${this.timeService.now()}`);
}
}For @Value('app.name') to work, ensure the value is previously loaded in the
ctxStore(@bigbyte/ctx module).
🔍 Detailed API
@App()
- Type: ClassDecorator
- Effects: Declares the MAIN component. Validates it is the first decorator on the class. Registers a listener on the 'last' event that adds the class to the
componentRegistryand then emits 'instantiated'. - Metadata applied: METADATA_COMPONENT_TYPE=MAIN, METADATA_DECORATOR_NAME=App.
- Constructor dependencies are injected.
@Component(options?: ComponentOptions without 'type')
- Registers the class with type COMPONENT. Allows
alias,scope, and other compatible fields defined in @bigbyte/ioc. - Validates uniqueness of the component decorator.
- Uses metadata to differentiate the type.
- Constructor dependencies are injected.
@Service()
- Same as @Component but semantically differentiated and without options. Type SERVICE.
- Constructor dependencies are injected.
@Inject()
- PropertyDecorator. Uses
design:typeto identify the constructor to inject. - Looks up the component in
componentRegistry. If not found, throws DecoratorError. - Defines a dynamic getter (does not overwrite the value, always accesses the current instance in the registry).
@Value(key: string)
- PropertyDecorator. Resolves
ctxStore.getByKey(key)and exposes its.valuevia a getter. - Immutable from the consumer perspective (no setter defined).
Internal Registration Flow
- Each decorator invokes
declareDecorator(name)when applied. - Each subscribes logic to the event
decoratorExecEvent.on('last', ...). executeDecorator(name)marks execution; when all declarations have been processed, the 'last' event fires the definitive registration.- @App emits 'instantiated' after populating the container, enabling startup hooks in higher layers.
🏗️ Architecture
Simplified module structure:
src/
├── index.ts # Public export point
├── constant/
│ └── index.ts # Decorator names and internal constants (LIBRARY_NAME, etc.)
└── decorator/
├── App.ts # Root decorator (MAIN) and instantiation trigger
├── Component.ts # Generic component decorator
├── Service.ts # Specialized logical decorator
├── Inject.ts # Type-based injection
└── Value.ts # Context value injectionKey dependencies:
- @bigbyte/utils (constants, logger, validation utilities).
- @bigbyte/ioc (componentRegistry, component types).
- @bigbyte/events (decorator execution lifecycle).
- @bigbyte/ctx (context storage for @Value).
- reflect-metadata (type metaprogramming).
⚠️ Error Handling
Relevant errors (from @bigbyte/utils/exception):
- DecoratorError: thrown when:
- Attempting to decorate a private property with @Inject or @Value.
- A component for the requested type in @Inject is not found.
- Decorator uniqueness rules are violated (utilities like
checkFirstDecorator,checkUniqueDecoratormay trigger internal exceptions).
Best practices:
- Ensure all decorated classes are exported (facilitates scanning in upper layers).
- Avoid side-effects requiring instances before the 'instantiated' event.
🔧 Advanced Examples
Chained Injection and Configuration Values
@Service()
class ConfigService {
get(key: string) { /* ... */ }
}
@Service()
class GreetingService {
constructor(private config: ConfigService) {}
message() { return `Hello ${this.config.get('user.name')}`; }
}
@Component()
class Greeter {
@Inject() private greeting!: GreetingService;
greet() { console.log(this.greeting.message()); }
}Using @Value for Feature Flags
@Component()
class FeatureToggle {
@Value('feature.new-ui') private enabled!: boolean;
isEnabled() { return !!this.enabled; }
}Root Pattern with @App
@App()
class Bootstrap {
@Inject() private greeter!: Greeter;
start() { this.greeter.greet(); }
}📄 License
This project is licensed under the Apache-2.0 license. See the LICENSE file for details.
Built with ❤️ by Jose Eduardo Soria Garcia (mailto:[email protected])
Part of the BigByte ecosystem
