A collection of utilities for large JavaScript projects with a consistent API.
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
The isotropic library follows several core principles:
All isotropic modules follow similar API patterns and naming conventions, making them predictable and easy to learn.
Most utilities favor a functional programming approach, prioritizing immutability and composability.
Isotropic embraces JavaScript's prototype-based inheritance model rather than trying to force class-based paradigms onto it.
Many components use a publish-subscribe pattern for extensibility and loose coupling.
Objects that need initialization follow consistent patterns for setup and teardown.
The isotropic ecosystem consists of numerous specialized modules. Here are some of the most commonly used:
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'
});
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
});
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();
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
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 |
The isotropic ecosystem includes development tools that ensure consistent code quality:
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
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)
Instead of installing the full isotropic package, we recommend installing only the specific modules you need:
npm install isotropic-make isotropic-pubsub
Then import and use them in your code:
import _make from 'isotropic-make';
import _Pubsub from 'isotropic-pubsub';
// Your implementation here
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.
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
new
keyword - Provides clear inheritance patterns
- Supports multiple inheritance through mixins
- Offers flexible initialization
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
Please refer to CONTRIBUTING.md for contribution guidelines.
If you encounter any issues, please file them at https://github.com/ibi-group/isotropic/issues