#Module error (might not be a valid name buh idk)
104 messages · Page 1 of 1 (latest)
Suggestion for @nimble stirrup:
:warning: Please do not screenshot code as it causes a number of issues:
- Ease of assistance: if someone wants to copy your code and correct it, they cannot. Making it easy for people to help you is in your best interests.
- Editorializing: it's common to try to make images small, which means you're likely to crop out code relevant to your issue
- Accessibility: wide images can be hard to read on mobile devices, and are impossible for screen readers.
- Legibility: you cannot read screenshots of code directly, instead you have to open them in an enlarged context.
- Bandwidth usage/clutter: some of our members use metered connections, and it is wasteful for them to download images of a text.
For a small amount of code, please use a code-block.
oh shii mb lemme paste then
forgot about that
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { TaskModel, Task } from 'src/models/tasks';
import { TasksService } from './tasks.service';
import { TasksController } from './tasks.controller';
import { JwtAuth } from 'src/utils/helper';
import { JwtService } from '@nestjs/jwt';
import { TaskGateway } from './tasks.sockets';
@Module({
imports: [
MongooseModule.forFeature([{ name: Task.name, schema: TaskModel }]),
],
controllers: [TasksController],
providers: [TasksService, JwtService, JwtAuth, TaskGateway],
})
export class TasksModule { }
import { SubscribeMessage, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Server } from 'socket.io';
import { TasksService } from './tasks.service';
@WebSocketGateway()
export class TaskGateway {
@WebSocketServer()
server: Server;
constructor(private taskService: TasksService) { }
@SubscribeMessage('getTasks')
async handleGetTasks(client: any, payload: { email: string }): Promise<void> {
const tasks = await this.taskService.getTasks(payload.email);
client.emit('tasks', tasks);
}
async broadcastTasks(email: string): Promise<void> {
const tasks = await this.taskService.getTasks(email);
this.server.emit('tasks', tasks);
}
}
[Nest] 306131 - 05/17/2024, 4:34:15 PM LOG [NestFactory] Starting Nest application...
[Nest] 306131 - 05/17/2024, 4:34:15 PM LOG [InjectorLogger] Nest encountered an undefined dependency. This may be due to a circular import or a missing dependency declaration.
[Nest] 306131 - 05/17/2024, 4:34:15 PM ERROR [ExceptionHandler] Nest can't resolve dependencies of the TaskGateway (?). Please make sure that the argument dependency at index [0] is available in the TasksModule context.
Potential solutions:
- Is TasksModule a valid NestJS module?
- If dependency is a provider, is it part of the current TasksModule?
- If dependency is exported from a separate @Module, is that module imported within TasksModule?
@Module({
imports: [ /* the Module containing dependency */ ]
})
Error: Nest can't resolve dependencies of the TaskGateway (?). Please make sure that the argument dependency at index [0] is available in the TasksModule context.
Potential solutions:
- Is TasksModule a valid NestJS module?
- If dependency is a provider, is it part of the current TasksModule?
- If dependency is exported from a separate @Module, is that module imported within TasksModule?
@Module({
imports: [ /* the Module containing dependency */ ]
})
Are you injecting the service into the socket gateway and the socket gateway into the service?
So you're creating a circular dependency
more or less
yh i think it's better i make a folder for it and import it instead
do i have to create a new module or it?
Let's take a step back: what are you trying to achieve with this?
so i have that socket class
and a service
i want the service to also use that socket class and it's functions
but also the socket class itself needs to have access to the service functions for some certain operations
just started nestjs so i'm a lil lost on things concerning structure
Is this for things like broadcasting a resource was created or updated?
yes
Okay. Rather than injecting the socket gateway into the service, I would suggest having the service expose an RxJS Subject that the socket gateway can subscribe to and then emit new values off of
Let me grab a link to my example
so almost the same way as guards?
tbh idek just remember seeing that RxJS thing in the guard imports
aii lemme check it out
RxJS is an asynchronous library for JS that works based off of Observables and Subjects. Nest's guards are able to return an observable and it will figure out how to properly wait for the value. But guards are not directly tied to Observables in any way
damn
i'm not understanding this thing
Might need some knowledge around how RxJS works to fully grasp it
i am getting the logic now
base assertion is that i will need to break the circular dependency right
Correct
what does the ongateway init type return or do
is it like once the sockets get started or run it should run some functions or ....?
That interface specifies that the afterInit method should be present in the class implementing the interface
which then means a new module folder
sorry for the continuous questions
i just wanna understand somethings
oh wait you are a nestjs dev
that's so cool
You don't necessarily need a new module
Using RxJS like this allows you to keep just the two classes in the same module without the circular dependency
If you want to go a different route though, you may need a new module
so basically rxjs implements some sort of inheritance?
Not at all
oh really or maybe not inheritance but like parameter passing and all that
oh wait i meant the ws
my bad
The Subject is essentially an array of objects/events that happen that can be added to using the subject.next() method inside the service. Then over in the gateway, you can subscribe to those events and let the gateway's ws server instance emit values based on the events
ohhhh
let me work out somethings on my own then i'll come back again
just to understand something for myself first before asking
Thank you
@open olive
this is it
Oof web sockets, that's a topic i usually avoid because i never used it before
my brain is literally boiling
i have used comples things before but i'm on a deadline
so everything is just overwhelming
but i'll figure it out
In a few minutes i think i can look into the docs of them
import { OnGatewayInit, SubscribeMessage, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Server } from 'socket.io';
import { TasksService } from '../tasks/tasks.service';
@WebSocketGateway()
export class TaskGateway implements OnGatewayInit {
@WebSocketServer()
server: Server;
constructor(private taskService: TasksService) { }
@SubscribeMessage('getTasks')
async handleGetTasks(client: any, payload: { email: string }): Promise<void> {
const tasks = await this.taskService.getTasks(payload.email);
client.emit('tasks', tasks);
}
afterInit(server: Server) {
this.taskService.getTasks.subscribe({
next: (email: string) => {
const tasks = this.taskService.getTasks(email);
this.server.emit('tasks', tasks);
}
})
}
async broadcastTasks(email: string): Promise<void> {
const tasks = await this.taskService.getTasks(email);
this.server.emit('tasks', tasks);
}
}```
so i got this
private events$ = new Subject<{ email: string }>
sync getTasks(email: string): Promise<Task[]> {
try {
const tasks = await this.taskModel.find({ email });
this.events$.next({ email })
return tasks;
} catch (err) {
throw new Error(err);
}
}
but the err is saying
~
what am i missing
this.service.getTasks() doesn't return an observable. Instead you should be looking at this.events$.subscribe()
then i would have to make it public
yh i saw that
do i need to add the asObservable or i can jst go straight to the subscribe
The asObservable is necessary as well
oh i forgot to call it
lets go
import { OnGatewayInit, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Server } from 'socket.io';
import { TasksService } from '../tasks/tasks.service';
@WebSocketGateway()
export class TaskGateway implements OnGatewayInit {
@WebSocketServer()
server: Server;
constructor(private taskService: TasksService) { }
afterInit(server: Server) {
this.taskService.events$.asObservable().subscribe({
next: (data) => {
server.emit('tasks', data)
}
})
}
async broadcastTasks(email: string): Promise<void> {
const tasks = await this.taskService.getTasks(email);
this.server.emit('tasks', tasks);
}
}
the broadcastTasks function is correct that way yes?
Where would you call the broadcast function from?
So you'd still have this circular dependency which undoes the entire reason for the Subject
i just remembered that lmao
so do i still subscribe to that one too?
or lemme check if you have any example on that
do i also need to initialize ws in the main.ts file like you did?
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import "dotenv/config"
import * as cookie from "cookie-parser"
import * as logger from "morgan"
const PORT: number = 3000 || +process.env.PORT;
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.setGlobalPrefix('api')
app.enableCors()
app.use(logger('dev'))
app.use(cookie(process.env.JWT_SECRET as string))
await app.listen(PORT, () => {
console.log(`Server running on port :::->${PORT}`);
});
}
bootstrap();```
oh ok ok
so how do you suggest i go about the broadcast
should that also be a subscribe event thing?
Essentially the same idea. You set up a subject and subscribe to it in the gateway
Yh plan on doing that when i get home
damn loadshedding did a number on me
so i decided to remove the broadcast message function
import { OnGatewayInit, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Server } from 'socket.io';
import { TasksService } from '../tasks/tasks.service';
@WebSocketGateway()
export class TaskGateway implements OnGatewayInit {
@WebSocketServer()
server: Server;
constructor(private taskService: TasksService) { }
afterInit(server: Server) {
this.taskService.events$.asObservable().subscribe({
next: (data) => {
server.emit('tasks', data)
}
})
}
}```
since it seems that the socket is subscribed to the taskservice class
so it is possibly listening for all value i believe
import { Injectable } from "@nestjs/common";
import { InjectModel } from "@nestjs/mongoose";
import { Model } from "mongoose";
import { Task } from "src/models/tasks";
import { Tasks } from "./tasks.dto";
import { Subject } from "rxjs";
@Injectable()
export class TasksService {
constructor(@InjectModel(Task.name) private taskModel: Model<Task>) { }
public events$ = new Subject<{ data: Task[] }>
async createTask(body: Tasks): Promise<{ message: string }> {
try {
const exist = await this.taskModel.findOne({ email: body.email });
if (!exist) {
return { message: "Task entry not found" };
}
exist.tasks.push(body);
await exist.save();
this.events$.next({ data: [exist] })
return { message: "Task created" };
} catch (err) {
throw new Error(err);
}
}
async getTasks(email: string): Promise<Task[]> {
try {
const tasks = await this.taskModel.find({ email });
this.events$.next({ data: tasks })
return tasks;
} catch (err) {
throw new Error(err);
}
}
and then this is how i am calling the subject thing
am i getting the logic correct
tbh did nothing here, web sockets isn't really something i know much of in nest
This post has been marked as resolved. :white_check_mark:
Please read through the conversation and resolution, if you are having the same issue. If you were the original author of the post and the issue is still fresh (within a few days) and you are still have having trouble, continue to reply here. If you are not the original author of the post or the post has aged, start a new thread linking this one as relevant to your problem, providing as much additional information as possible.
it is /solved btw
Crazy
Changed it?
changed what?
Like did they change the prompt?
always has been /solved
behaviour has been tweaked over time tho
Oh wait mb
Thought it worked in that previous thread till i realize you re did it