Currently, I am in the process of developing an API using NestJS.
To enhance my API, I decided to integrate Redis and formulated a Dynamic Module that establishes a connection with Redis.
Furthermore, I incorporated Decorators for utilizing the redis connection.
However, I encountered an issue. Although I can access the Decorator in other services,
whenever I attempt to access it within the Module located in the same directory as the Decorator, I encounter a TypeError.
@InjectRedisGraph(MainGraph) private readonly graph: Graph,
^
TypeError: (0 , redis_graph_connection_decorator_1.InjectRedisGraph) is not a function
Here are the solutions I have attempted so far:
- I tried setting both absolute and relative paths for import, but neither succeeded
- Exported a generic console.log function, which functions properly and gets executed
- Added @Injectable decorator to the Module, however, it did not resolve the problem (Although the Injectable decorator itself did not trigger a TypeError)
- Moving the declaration into the Module file does work, nevertheless, I prefer to keep the files separate
Upon examining the transpiled JS code, the exports of the decorator appear to be correct.
VS Code has no issues resolving all classes/functions.
When transpiling, tsc does not report any errors.
All configurations align with the default NestJS config settings.
Hopefully, this oversight is on my end. As a newcomer to NestJS and Typescript Decorators, I currently find myself a bit lost.
The Code: decorator
import { Inject } from '@nestjs/common'
import { RedisClientIdentifier } from './redis-graph-connection.provider'
/**
* Simple decorator to make usage of graphredis more verbose
*/
export const InjectRedisGraph = (graph: symbol): ParameterDecorator => {
return Inject(graph)
}
export function doesExport() {
console.log("It does")
}
module
import { DynamicModule, Logger, OnApplicationShutdown } from '@nestjs/common'
import { createRedisGraphProviders } from './redis-graph-connection.provider'
import { RedisClientOptions } from '@redis/client'
import { doesExport, InjectRedisGraph } from './redis-graph-connection.decorator'
import { MainGraph } from '../redis-store.constants'
import { Graph } from '@redis/graph'
export class RedisGraphModule implements OnApplicationShutdown {
static logger = new Logger('redis-graph-client')
static async forRootAsync(
options: RedisGraphModuleOptions,
): Promise<DynamicModule> {
const providers = await createRedisGraphProviders(options)
return {
module: RedisGraphModule,
providers,
exports: providers,
}
}
// |-> This throws TypeError, not a function
constructor(@InjectRedisGraph(MainGraph) private readonly graph: Graph) {
doesExport()
}
onApplicationShutdown() {
// do some graph cleanup
}
}
some other service, This works
import { Injectable, Logger } from '@nestjs/common'
import { EvidenceStore } from 'src/common/evidence-store.interface'
import { InjectRedisGraph } from 'src/redis-store/redis-graph-connection/redis-graph-connection.decorator'
import { MainGraph } from './redis-store.constants'
import { Graph } from '@redis/graph'
@Injectable()
export class RedisStore implements EvidenceStore {
private readonly logger = new Logger('redis-graph-collector')
constructor(
@InjectRedisGraph(MainGraph) private readonly redisGraph: Graph,
) {}
...
redis-graph-connection.provider
import { createClient, Graph } from 'redis'
import { Provider } from '@nestjs/common'
import { RedisGraphModule, RedisGraphModuleOptions } from './redis-graph-connection.module'
export const RedisClientIdentifier = Symbol('redisClient')
export async function createRedisGraphProviders(
options: RedisGraphModuleOptions,
): Promise<Array<Provider>> {
const client = createClient(options.redisOptions)
client.on('error', (err: Error) => {
RedisGraphModule.logger.error(err.message, err.stack)
})
await client.connect()
RedisGraphModule.logger.log('Connected')
const providers: Array<Provider> = [
{
provide: RedisClientIdentifier,
useValue: client,
},
]
options.graphs.forEach((graphName) => {
providers.push({
provide: graphName,
useValue: new Graph(client, graphName.toString()),
})
RedisGraphModule.logger.log(`Created graph for ${graphName.toString()}`)
})
return providers
}