#Module error (might not be a valid name buh idk)

104 messages · Page 1 of 1 (latest)

nimble stirrup
#

I added a socket class to my routes and put it in the constructor of the controller class but it doesn't seem to find it.

north pineBOT
#

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.

nimble stirrup
#

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 */ ]
  })
icy gyro
#

Are you injecting the service into the socket gateway and the socket gateway into the service?

nimble stirrup
#

yes

#

or should i just make it a different file and import it instead?

icy gyro
#

So you're creating a circular dependency

nimble stirrup
#

yh i think it's better i make a folder for it and import it instead

nimble stirrup
icy gyro
#

Let's take a step back: what are you trying to achieve with this?

nimble stirrup
#

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

icy gyro
nimble stirrup
#

yes

icy gyro
#

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

nimble stirrup
#

so almost the same way as guards?

icy gyro
#

What do you mean?

nimble stirrup
icy gyro
#

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

nimble stirrup
#

damn
i'm not understanding this thing

icy gyro
#

Might need some knowledge around how RxJS works to fully grasp it

nimble stirrup
#

i am getting the logic now

#

base assertion is that i will need to break the circular dependency right

icy gyro
#

Correct

nimble stirrup
#

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 ....?

icy gyro
#

That interface specifies that the afterInit method should be present in the class implementing the interface

nimble stirrup
#

sorry for the continuous questions
i just wanna understand somethings

#

oh wait you are a nestjs dev
that's so cool

icy gyro
#

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

nimble stirrup
#

so basically rxjs implements some sort of inheritance?

icy gyro
#

Not at all

nimble stirrup
#

oh wait i meant the ws

#

my bad

icy gyro
#

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

nimble stirrup
#

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

open olive
nimble stirrup
#

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

open olive
nimble stirrup
#
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

icy gyro
#

this.service.getTasks() doesn't return an observable. Instead you should be looking at this.events$.subscribe()

nimble stirrup
#

then i would have to make it public

nimble stirrup
#

yh i saw that

#

do i need to add the asObservable or i can jst go straight to the subscribe

icy gyro
#

The asObservable is necessary as well

nimble stirrup
#

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?

icy gyro
#

Where would you call the broadcast function from?

nimble stirrup
#

it's in the task service

#

lemme show

icy gyro
#

So you'd still have this circular dependency which undoes the entire reason for the Subject

nimble stirrup
#

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();```
icy gyro
#

No, I only did that cause I was using Ws instead of Socket.IO

nimble stirrup
#

oh ok ok

#

so how do you suggest i go about the broadcast
should that also be a subscribe event thing?

icy gyro
#

Essentially the same idea. You set up a subject and subscribe to it in the gateway

nimble stirrup
#

Yh plan on doing that when i get home

nimble stirrup
#

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

nimble stirrup
nimble stirrup
#

yes i was correct

#

thanks @icy gyro @open olive

#

... solved

open olive
north pineBOT
#

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.

open olive
nimble stirrup
nimble stirrup
open olive
nimble stirrup
open olive
#

behaviour has been tweaked over time tho

nimble stirrup
#

Oh wait mb

Thought it worked in that previous thread till i realize you re did it