isotropic
v0.15.0
Published
A collection of utilities for large JavaScript projects with a consistent API
Downloads
27
Readme
isotropic
A collection of utilities for large JavaScript projects with a consistent API.
Overview
Isotropic is a modular library of JavaScript utilities that work together to provide a cohesive development experience for complex applications. Rather than importing this package directly, you'll typically want to import only the specific isotropic modules your project needs.
This package serves as:
- A central location for documentation and discovery of the entire isotropic ecosystem
- A reference implementation demonstrating how the modules integrate
- A convenient way to explore the capabilities of all isotropic modules
Philosophy
The isotropic library follows several core principles:
1. Consistent API Design
All isotropic modules follow similar API patterns and naming conventions, making them predictable and easy to learn.
2. Functional Approach
Most utilities favor a functional programming approach, prioritizing immutability and composability.
3. Prototype-Based Object Model
Isotropic embraces JavaScript's prototype-based inheritance model rather than trying to force class-based paradigms onto it.
4. Event-Driven Architecture
Many components use a publish-subscribe pattern for extensibility and loose coupling.
5. Predictable Lifecycle Management
Objects that need initialization follow consistent patterns for setup and teardown.
Core Modules
The isotropic ecosystem consists of numerous specialized modules. Here are some of the most commonly used:
isotropic-make
A powerful factory function that creates constructor/factory functions with support for inheritance, mixins, and initialization.
Key Features:
- Works both as a constructor (with
new) and factory function (withoutnew) - Clean prototype inheritance with explicit parent references
- Multiple inheritance through mixins
- Static properties and initialization
- Predictable inheritance patterns
Example:
import _make from 'isotropic-make';
// Create a Person constructor
const _Person = _make({
greet() {
return `Hello, my name is ${this.name}`;
},
_init({
age,
name
}) {
this.age = age;
this.name = name;
return this;
}
});
// Create an Employee that inherits from Person
const _Employee = _make(_Person, {
work() {
return `${this.name} is working on ${this.project}`;
},
_init({
age,
name,
project
}) {
// Call parent initialization
Reflect.apply(_Person.prototype._init, this, [{
age,
name
}]);
this.project = project;
return this;
}
});
// Use either as constructor or factory
const john = new _Employee({
age: 30,
name: 'John',
project: 'Website'
});
const jane = _Employee({
age: 28,
name: 'Jane',
project: 'API'
});isotropic-pubsub
A powerful and flexible event system implementing the publish-subscribe pattern with advanced lifecycle features.
Key Features:
- Complete event lifecycle with before, on, and after stages
- Event distribution through object hierarchies
- Prevention, stopping, or modification of events during their lifecycle
- Customizable dispatcher behavior for each event type
- Type-based message routing
Example:
import _Pubsub from 'isotropic-pubsub';
// Create a pubsub instance
const pubsub = _Pubsub();
// Subscribe to different lifecycle stages
pubsub.before('save', event => {
if (!event.data.isValid) {
event.preventDefault(); // Prevents the default action
}
});
pubsub.on('save', event => {
console.log('Saving data:', event.data);
});
pubsub.after('save', event => {
console.log('Save completed at:', Date.now());
});
// Publish an event
pubsub.publish('save', {
data: { id: 123, name: 'Test' },
isValid: true
});isotropic-initializable
An observable initialization lifecycle for JavaScript objects ensuring parent-to-child initialization sequence.
Key Features:
- Predictable parent-to-child initialization order
- Support for both synchronous and promise-based initialization
- Observable lifecycle events
- Selective initialization of specific classes in the hierarchy
- Built-in error propagation
Example:
import _Initializable from 'isotropic-initializable';
import _make from 'isotropic-make';
// Base component with initialization
const _BaseComponent = _make(_Initializable, {
_initialize() {
console.log('Base initializing...');
this.baseReady = true;
// Can return a Promise for async initialization
}
});
// Derived component
const _EnhancedComponent = _make(_BaseComponent, {
_initialize() {
console.log('Enhanced initializing...');
// Safe to use this.baseReady here
this.enhancedReady = true;
}
});
// Create with delayed initialization
const component = _EnhancedComponent({
initialize: false
});
// Start initialization when needed
component.initialize();isotropic-cluster
A reusable platform to manage Node.js process clusters with a clean API for primary/worker communication.
Key Features:
- Simple API for cluster management
- Reliable worker lifecycle
- Structured message passing between primary and workers
- Built-in round-robin worker selection
- Error handling and worker replacement
- Observable events for worker lifecycle
All Modules
The isotropic ecosystem includes the following modules:
| Module | Description | |--------|-------------| | bunyan-stream-isotropic | Human-friendly output for Bunyan logs | | isotropic-character-fold | Replaces special characters with their basic counterparts | | isotropic-cluster | Manages Node.js process clusters | | isotropic-console | Configured instance of the Node.js console | | isotropic-create | Creates objects with specific prototypes while maintaining constructor properties | | isotropic-duration-to-string | Converts duration values to human-readable strings | | isotropic-error | Enables nested error objects with complete stack traces | | isotropic-for-in | Object iteration utility similar to Array.forEach | | isotropic-initializable | Observable initialization lifecycle for objects | | isotropic-later | Consistent interface for asynchronous timers | | isotropic-logger | Singleton logger using Bunyan | | isotropic-make | Factory function for creating constructors with inheritance and mixins | | isotropic-mixin | Utility for creating mixins | | isotropic-mixin-prototype-chain | Utilities for working with prototype chains in mixins | | isotropic-mutex | Local-process advisory access locks | | isotropic-natural-sort | Sorting function that handles strings in a natural way | | isotropic-property-chainer | Establishes prototype chains among object properties | | isotropic-prototype-chain | Utilities for working with prototype chains | | isotropic-pubsub | Flexible publish-subscribe event system | | isotropic-timeout | Implements timeouts for promises or callback functions | | isotropic-value-to-source | Serializes data to formatted JavaScript code |
Development Tools
The isotropic ecosystem includes development tools that ensure consistent code quality:
eslint-plugin-isotropic
A set of ESLint rules and configurations designed specifically for isotropic projects:
- Enforces consistent code style
- Encourages proper module structure
- Promotes use of modern JavaScript features
- Provides natural sorting for variables and object keys
- Enforces underscore-prefixed module-level variables
isotropic-dev-dependencies
A shared package of common development dependencies and configurations:
- Single source of truth for development dependencies
- Shared configurations for Babel, ESLint, c8, and other tools
- Automated setup of git hooks
- High code coverage standards (100% targets)
Getting Started
Instead of installing the full isotropic package, we recommend installing only the specific modules you need:
npm install isotropic-make isotropic-pubsubThen import and use them in your code:
import _make from 'isotropic-make';
import _Pubsub from 'isotropic-pubsub';
// Your implementation hereDesign Decisions
Underscore Prefix Convention
You may notice that isotropic modules use underscore prefixes for variables. This convention helps distinguish module-level (top-scope) variables from local variables and follows the "Approachable Encapsulation" philosophy described in the isotropic-make documentation.
Functional Factory Pattern
The isotropic-make module uses a pattern that combines constructor functions with factory functions, providing the best of both worlds. This approach:
- Eliminates issues with forgetting the
newkeyword - Provides clear inheritance patterns
- Supports multiple inheritance through mixins
- Offers flexible initialization
Event Lifecycle
The event system in isotropic-pubsub provides before/on/after stages for each event, giving fine-grained control over the event lifecycle. This enables:
- Validation before an event executes
- Main processing during the event
- Cleanup or notification after the event
Contributing
Please refer to CONTRIBUTING.md for contribution guidelines.
Issues
If you encounter any issues, please file them at https://github.com/ibi-group/isotropic/issues
