NodeJS Contextual Dependency Injection using native async_hooks
see https://nodejs.org/api/async_hooks.html
yarn add nctx
or
npm i nctx
ctx/app.js
const nctx = require("nctx")
module.exports = nctx.create(Symbol("app"))
ctx/req.js
const nctx = require("nctx")
const reqCtx = nctx.create(Symbol("req"))
reqCtx.createAppMiddleware = () => {
return (req, res, next) => {
reqCtx.provide(()=>{
reqCtx.share(req)
res.on("finish", () => {
reqCtx.endShare(req)
})
reqCtx.set("req", req)
next()
})
}
}
reqCtx.createRouterMiddleware = () => {
return function (req, _res, next) {
reqCtx.share(req)
if (next) {
next()
}
}
}
module.exports = reqCtx
app.js
const express = require("express")
const reqCtx = require("~/ctx/req")
const app = express()
app.use(reqCtx.createAppMiddleware())
// middlewares context
app.use(async (req, _res, next) => {
const reqLogger = logger.child({ path: req.path })
reqCtx.set("logger", reqLogger)
next()
})
const router = express.Router()
router.use(reqCtx.createRouterMiddleware())
app.use(router)
// now you can get contextual logger from anywhere you call reqCtx under async tree
router.get("/", async ()=>{
const reqLogger = reqCtx.get("logger")
// the reqLogger is specific to the query
})
const nctx = require("nctx")
const funcCtx1 = nctx.create()
const func = async () => {
const foo = funcCtx1.require("foo")
return `foo=${foo}`
}
const main = async () => {
funcCtx1.provide(()=>{
funcCtx1.set("foo", "bar")
const result = await Promise.all([
nctx.fork([funcCtx1], () => {
funcCtx1.set("foo", "jo")
// here func is executed under the forked context 1
return func()
}),
nctx.fork([funcCtx1], () => {
funcCtx1.set("foo", "devthejo")
// here func is executed under the forked context 2
return func()
}),
// here func is executed under original context
func(),
])
})
console.log(result)
}
main()
We welcome contributions! If you encounter a bug or have a feature suggestion, please open an issue. To contribute code, simply fork the repository and submit a pull request.
This repository is mirrored on both GitHub and Codeberg. Contributions can be made on either platform, as the repositories are synchronized bidirectionally.
For more information: