https://github.com/naikus/app-context
A tiny, dead simple context & dependency manager for node-js applications
https://github.com/naikus/app-context
application-context nodejs-dependency-manager nodejs-service-container
Last synced: 3 months ago
JSON representation
A tiny, dead simple context & dependency manager for node-js applications
- Host: GitHub
- URL: https://github.com/naikus/app-context
- Owner: naikus
- License: mit
- Created: 2021-06-10T06:20:55.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2025-04-19T17:42:38.000Z (about 1 year ago)
- Last Synced: 2025-04-19T20:23:08.881Z (about 1 year ago)
- Topics: application-context, nodejs-dependency-manager, nodejs-service-container
- Language: JavaScript
- Homepage:
- Size: 73.2 KB
- Stars: 1
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
## app-context
A tiny, dead simple context & dependency container for node-js applications. Now checks for
missing modules and cyclic dependencies
### Usage
In your package.json, add it as a dependency
```json5
{
"name": "my-app",
"version": "1.0.0",
"description": "My Application",
"main": "index.js"
// ...
"dependencies": {
// ...other deps
"app-context": "github:naikus/app-context#error-reporting"
}
}
```
Define a module/service or multiple services (in their own files)
```js
// File users/index.js
const createUserService = require("./service");
/**
* @type {ModuleDefn}
*/
module.exports = {
name: "users",
/**
* Initializes the users module
* @param {AppContext} context The application context
*/
async initialize(context) {
// "api-router" & "persistence" are modules that are registered with the app context elsewhere
const [apiRouter, db] = await context.dependency(["api-router", "db"]),
service = createUserService(db);
// Alternatively you can also use the following syntax
context.dependency(["api-router", "db"], (apiRouter, db) => {
// Do something
});
// Get notified for events from context or other modules
const unsub = context.on("some:event", data => {
// do something
});
// Emit events
context.emit("users:add", {name: "Alice"});
// Whatever you return here will me made available via context.getModule(name) which is safe
// to call after context has started
// const userService = context.getModule("users");
return service;
}
};
```
Then in your main file, wire all the modules. The order is not important, app-context will instantiate
your modules in the right order.
```js
const apiRouter = require("./api-router"),
db = require("./db"),
users = require("./users");
const AppContext = require("app-context"),
context = AppContext.create();
// ....
// Later in your main start function
context.register(users)
.register(apiRouter)
.register(db)
// You can also register inline modules
.register({
name: "config",
initialize: () => ({
property: "value"
})
});
try {
await context.start();
logger.info("Application started 🚀");
context.emit("app:initialize");
}catch(error) {
logger.error("Application failed to start", error);
process.exit(1);
};
```
### How to get around cyclic dependencies
If your modules depend on one another, i.e. cyclic dependencies, you can get around by registering an
event listener on app-context
```js
const context = AppContex.create();
context.register({
name: "module_a",
async initialize(ctx) {
const [moduleB] = await ctx.dependency("module_b");
// Do something with moduleB...
moduleB.sayHello();
// Return the actual module
return {
sayHello() {
console.log("Hello from module_a");
}
};
}
});
context.register({
name: "module_b",
async initialize(ctx) {
// This will throw error (cyclic dependencies)
// const [moduleA] = await ctx.dependency("module_a");
// Instead do this:
ctx.once("module:module_a", moduleA => {
// module_a is now available
});
// Return the actual module
return {
sayHello() {
console.log("Hello from module_b");
}
};
}
});
context.start();
```