Comments (9)
@IGZgustavomarin you can use inject
to have Awilix build the middleware:
const { createController, inject } = require('awilix-express')
// Assuming `cacheMiddleware` is a factory function
const { cacheMiddleware } = require('./your/cache/middleware')
class TodoController {
constructor ({ todosService }) {
this.todos = todoService
}
getAll(req, res) => {
return res.send(this.todosService.getTodos())
}
}
module.exports = createController(TodoController)
.get('/todos', 'getAll', {
before: [ inject(cacheMiddleware) ]
})
from awilix-express.
Ok, this way works, but my middleware gets created each time I call the endpoint. Even if I set the lifetime to SINGLETON
. I'm doing this:
const cacheProducts = ({ config }) => {
return (req, res, next) => {
/** cache logic here, return memory data or return next() **/
}
return cache
}
cacheProducts[RESOLVER] = {
lifetime: Lifetime.SINGLETON
}
module.exports = cacheProducts
Is is possible to inject the same middleware every time? Otherwise, it never hits my cache data.
FYI: All this was working on previous version with code like this:
classs ProductsRouter {
/** code **/
this.router = Router()
this.router.get('/products',
cacheProductsMiddleware, // cache layer
inject('getAllProducts'), // data access layer
this.getAll // <- the endpoint handler
)
from awilix-express.
Lifetimes only apply to registrations, not resolvers built directly with container.build
(which is what inject
does), so you want to wrap it to use the registration:
module.exports = createController(TodoController)
.get('/todos', 'getAll', {
// assuming your middleware registration is named "cacheService"
before: [ inject(({ cacheService }) => cacheService) ]
})
from awilix-express.
In fact, Awilix has a resolver for this called aliasTo
which does exactly what the previous example does:
const { aliasTo } = require('awilix')
module.exports = createController(TodoController)
.get('/todos', 'getAll', {
// assuming your middleware registration is named "cacheService"
before: [ inject(aliasTo('cacheService')) ]
})
Hope this helps. 😄
from awilix-express.
Ok, now the middleware gets injected each time. But the cache layer makes some patching to the Response
object that doesn't work with inject
, meaning it never cache anything. I think the middleware function that inject
actually adds, collides with the apicache
(npm module) that I'm using.
Is there a way to create a controller and register the routes differently?
from awilix-express.
But the cache layer makes some patching to the Response object that doesn't work with inject, meaning it never cache anything
How so?
How do you register cacheService
? It would have to be singleton. Also, that cacheProducts
middleware has return cache
as well as return (req, res) => ...
, is that a typo in the example?
Could you try creating a minimal reproduction repository? That would make it way easier for me to help you, cause I'm certain we can make it work. 😄
from awilix-express.
Finally solve it. It turns out that the cache layer didn't work with HEAD
request only and that was messing my example. It works as intended. Sorry about that!
I've separated the logic into two controllers, like this:
mainRouter
.use(loadControllers('cache/*'))
.use(loadControllers('products/*'))
Each of those folders contains a class wrapped with a createController
call. But I noticed that on each request a new instance is created. This is too expensive for the cache layer (ex: connection, warmup, etc). Is it possible to make that instance a singleton?
My cache controllers is as this:
class ProductsCache {
constructor ({ config }) {
/** THIS IS CALLED ON EACH REQUEST **/
this.cacheAll = apicache.options({
...(config.cache.defaultConfig),
enabled: config.cache.defaultConfig.enabled === 'yes'
})
.middleware(config.cache.expiration.productList)
}
deleteAll = (req, res) => {
res.send(apicache.clear('/api/products'))
}
}
module.exports = createController(ProductsCache)
.get('/api/products', 'cacheAll')
.delete('/api/products/_cache', 'deleteAll')
I tried as a function instead of class, but it also gets called on each request. Can that behavior be changed?
from awilix-express.
The whole point is for the controller to be instantiated with each request, so you can inject request-specific stuff in the constructor. 😄
Seems to me you want the apicache
to be a singleton.
// In your container config
const apicache = require('apicache')
container.register({
productCache: asFunction(
({ config }) =>
apicache
.options({
...(config.cache.defaultConfig),
enabled: config.cache.defaultConfig.enabled === 'yes'
})
.middleware(config.cache.expiration.productList)
)
.singleton()
})
// Controller
class ProductsCache {
constructor ({ productCache }) {
this.cacheAll = productCache
}
deleteAll = (req, res) => {
res.send(apicache.clear('/api/products'))
}
}
module.exports = createController(ProductsCache)
.get('/api/products', 'cacheAll')
.delete('/api/products/_cache', 'deleteAll')
from awilix-express.
Thanks, I did something similar to that. 🎉
from awilix-express.
Related Issues (19)
- Add TypeScript Definition file (index.d.ts) HOT 3
- Cannot convert a Symbol value to a string HOT 4
- Integrate with awilix-router-core HOT 4
- Trying minimal example HOT 1
- More descriptive error messages when controller method attempting to be invoked does not exist HOT 1
- Can we use express-promise-router instead? HOT 2
- Scoped logger per request? HOT 4
- Cannot call a class as a function HOT 5
- Injecting dependencies per route instead of when creating controller HOT 4
- Thank you for your contributions HOT 1
- unhandledRejection when returning promises from routes HOT 4
- param decorator
- [question] "@before" middleware with injected dependencies HOT 1
- build: expected targetOrResolver to be a function or class, but got '...' HOT 3
- Resloving dependencies inside @before HOT 1
- Awilix 5.x is out HOT 2
- Awilix 7.x HOT 8
- Awilix 8.0 peerDependency HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from awilix-express.