instance-manager


Manage references to dynamically created classes and their instances.
🪑 Table of Content
🧰 Features
- Useful for managing references to dynamically-created classes and their
instances
- If you use class factory functions to create classes, you can store the class
config along with the class in
instance-manager
- Access classes and their instances using primitives (numbers)
- Classes and instances are weakly-references, so they will be
garbage-collected
🔮 Background
This package is used to enable loader and plugin instances created from
dynamically created classes to share information in Webpack, effectively using
a single dynamically created instance to behave both as a loader and a plugin.
If you need that functionality, head over to
ploadin, where the functionality has
been abstracted.
This package can be used for more cases. The problem faced can be generalized
as follows:
- There are dynamically created classes with unknown number of instances.
- You need to access a specific instance of a specific class.
- You are unable to pass the instance reference directly.
👶 Install
npm install instance-manager
Then in your file
const InstanceManager = require('instance-manager').default;
const im = new InstanceManager();
Or if using TypeScript
import InstanceManager from 'instance-manager';
const im = new InstanceManager();
🚀 Usage
Simple usage
const InstanceManager = require('instance-manager');
const im = new InstanceManager();
const classFactory = (options) => {
class MyClass {
hello() {
return options.message;
}
}
return MyClass;
};
const myClassOptions = { param: 42 };
const MyDynamicClass = classFactory(myClassOptions);
const arrayClassId = im.addClass(Array);
const myClassId = im.addClass(MyDynamicClass, myClassOptions);
im.getClassById(arrayClassId) === Array;
im.getClassId(Array) === arrayClassId;
im.getClassOptions(MyDynamicClass) === myClassOptions;
im.getClassOptionsById(myClassId) === myClassOptions;
im.removeClass(Array);
const instanceId1 = im.addInstance(new MyDynamicClass());
const anotherInstance = new MyDynamicClass();
const anotherId = im.addInstance(anotherInstance);
const sameId = im.getInstanceId(anotherInstance);
anotherId === sameId;
const myNum = new Number('2');
const numInstanceId = im.addInstance(myNum);
im.getClassId(Number);
im.getClassInstance(MyDynamicClass, anotherId) === anotherInstance;
const klass = im.getClassById(myClassId);
im.getClassInstance(klass, anotherId) === anotherInstance;
im.removeClassInstance(MyDynamicClass, instanceId1);
im.removeInstance(myNum);
Advanced usage
Advanced usage is shown with TypeScript.
Problem
Imagine we have the following 3 files:
class-factory.ts - defines a class factory.
create-message.ts - dynamically creates a class and instance. Sends a
message that is read by listener.
listener.ts - reads message, needs to access an instance that created the
message, but doesn't have a way to get the reference directly.
export default classFactory = (data: any) => {
class MyClass {
makeMessage(senderContext: any) {
}
doSomethingElseWithData(listenerContext: any) {
}
}
return MyClass;
};
import classFactory from './class-factory';
import someData from './some-data';
import otherData from './other-data';
import messageQueue from './message-queue';
const CustomClass = classFactory(someData);
const customInstance = new CustomClass(otherData);
const senderContext = this;
const message = customInstance.makeMessage(senderContext);
messageQueue.send(message);
import messageQueue from './message-queue';
messageQueue.listen((listenerContext, message) => {
});
Solution
We will use the instance-manager to store references to each newly created
class and instance and we will attach these IDs as properties of those classes
and instance.
We will then send the IDs as strings through the message.
The listener will be able to read the IDs, and will be able to request the
correct instances from our instance of instance-manager.
import InstanceManager from 'instance-manager';
const provider = new InstanceManager<any, any>();
export default provider;
import provider from './provider';
export default classFactory = (data: any) => {
class MyClass {
constructor() {
this._instanceId = provider.addInstance(this);
}
}
MiniExtractPlugin._classId = provider.addClass(MyClass);
return MyClass;
};
import classFactory from './class-factory';
import someData from './some-data';
import otherData from './other-data';
import messageQueue from './message-queue';
const CustomClass = classFactory(someData);
const customInstance = new CustomClass(otherData);
const senderContext = this;
const message = customInstance.makeMessage(senderContext);
const { _classId, _instanceId } = customInstance;
messageQueue.send(`${message}?classId=${_classId}&instanceId=${_instanceId}`);
import messageQueue from './message-queue';
import provider from './provider';
import { parseMessage } from './some-utils';
messageQueue.listen((listenerContext, message) => {
const { classId, instanceId } = parseMessage(message);
const klass = provider.getClassById(classId);
const instance = provider.getClassInstance(klass, instanceId);
instance.doSomethingElseWithData(listenerContext);
});
🤖 API
Full API documentation can be found here.
⏳ Changelog
This projects follows semantic versioning. The
changelog can be found here.
🛠 Developing
If you want to contribute to the project or forked it,
this guide will get you up and going.
🏗 Roadmap
This package is considered feature-complete. However, if you have ideas how it
could be improved, please be sure to share it with us by opening an issue.
🤝 Contributing
Contributions, issues and feature requests are welcome! Thank you ❤️
Feel free to dive in! See current issues,
open an issue, or
submit PRs.
How to report bugs, feature requests, and how to contribute and what
conventions we use is all described in the
contributing guide.
When contributing we follow the
Contributor Covenant.
See our Code of Conduct.
🧙 Contributors
Contributions of any kind welcome. Thanks goes to these wonderful people ❤️
Recent and Top Contributors

Generated using Hall of Fame.
All Contributors
Contribution type emoji legend
No additional contributors. Be the first one!
This project follows the all-contributors specification.
⭐ Show your support
Give a ⭐️ if this project helped you!
🔗 Related Projects
👨🔧 Maintainers
👤 Juro Oravec
📝 License
Copyright © 2020 Juro Oravec.
This project is MIT licensed.