How to add relation on microservices on Prisma using NestJS? - javascript

Schema on User Management service:
model User {
id String #id #default(uuid())
username String #unique
email String #unique
password String
}
Schema on File management service:
model File {
id String #id #default(uuid())
user_id String
user User #relation(fields: [user_id], references: [id])
file_name String
file_description String
file_url String
file_hash String
}
My user management service and file management service is different repository using Nest Js, Thank You!
I want to add relation on file model to user model

To add a relation between the File and User models in your Prisma setup with NestJS, you'll need to perform the following steps:
Connect to the appropriate Prisma service(s) from your NestJS application(s).
Make sure that the User and File models in your Prisma schema have the necessary fields for the relation, as you have defined above.
In your NestJS application, create a service that retrieves the appropriate user for each file, based on the user_id field. You can use the prisma-client package to query the Prisma API for the relevant data.
In your NestJS controller(s), use the service from step 3 to fetch the relevant data and return it in the API response.
Here's an example of what the service from step 3 might look like:
import { Injectable } from '#nestjs/common';
import { PrismaClient } from '#prisma/client';
#Injectable()
export class FilesService {
private prisma = new PrismaClient();
async getFilesWithUser() {
const files = await this.prisma.file.findMany({
include: {
user: true,
},
});
return files;
}
}
And here's an example of what the controller:
import { Controller, Get } from '#nestjs/common';
import { FilesService } from './files.service';
#Controller('files')
export class FilesController {
constructor(private readonly filesService: FilesService) {}
#Get()
async getFilesWithUser() {
return this.filesService.getFilesWithUser();
}
}

Related

How can I export my model's properties types from Prisma Schema?

Lets say I have this Prisma Schema :
model User {
id String #id #unique #default(dbgenerated("gen_random_uuid()")) #db.Uuid
email String #unique
username String
}
Is there a way I can get lets say email's type in my app ?
One options I can come with is a file that will export types but that way everytime I make a change to my prisma schema I will have to go there and manually edit the type.
Prisma by default generates types for all your models.
You could import it like this:
import { PrismaClient, User } from '#prisma/client';
Your models will always be in sync with your schema file, anytime you change the schema file, you could execute npx prisma generate to update the PrismaClient and the generated types for your models.

How do I configure NestJS to run mongosh scripts

I have the need to dynamically create mongo databases when a new user is registered on a SaaS platform.
How do I configure NestJS to run the scripts needed, to create the database, as well as how to dynamically connect with database created for each user?
And are there any better approaches to my usecase?
New User => Create New Database for them, and store details in the main SaaS database.
When user login, fetch DB details from main database, and create a connection to it, to read their data.
I don't see the need to create a new db for each user. Why not craeting a users collection and than for each user create a new object. Mongo object can store quite a lot of information.
I'm not a pro in nestjs, but I don't think that there is a way to dynamically connect more db's. When you start your app a mongoDB instance is initiated, don't forget that all classes in nestjs are singletones.
So, I was able to make it thus.
I created a database service class, in it, I used the MongooseModuleOptions to create a new connection, and injecting the Request Scope to it, I extracted the database name from the request and dynamically pass it to the uri in the createMongooseOptions method and that dynamically creates a connection.
import { Inject } from '#nestjs/common';
import { MongooseOptionsFactory, MongooseModuleOptions } from '#nestjs/mongoose';
import { REQUEST } from '#nestjs/core';
import { Request } from 'express';
export class DatabaseService implements MongooseOptionsFactory{
constructor(
#Inject(REQUEST) private readonly request: Request) {
}
createMongooseOptions(): MongooseModuleOptions {
const urii = process.env.CLUSTER+'/'+this.request.body.dbName+"?retryWrites=true&w=majority"
return {
uri: urii
};
}
}
Then inside the users module, I insert data into a collection specified inside the schema, and that automatically uses the connection to create a database, collection and entry, if it exists, it uses the database and collection.
import { Inject, Injectable } from '#nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { User, UserDocument } from './schemas/user.schema';
import { InjectConnection, InjectModel } from '#nestjs/mongoose';
import { Model } from 'mongoose';
#Injectable()
export class UserService {
constructor(#InjectModel(User.name) private userModel:Model<UserDocument>){}
async create(createUserDto: CreateUserDto) {
const createdUser = new this.userModel(createUserDto)
return createdUser.save()
}
}
That worked perfectly for me.
Thank you all πŸ™πŸ™πŸ™

Mongoose InjectModel model type when using Schema without decorators

So I'm trying to implement user management using Nest.js and Mongoose. My DB design tool has generated for me Schema in new mongoose.Schema({ .... }); format, so for now I have schema ready. The problem I've encountered is when trying to #InjectModel in User's service:
#Injectable()
export class UsersService {
constructor(#InjectModel('User') private userModel: Model<>) {}
async getAll() {
//code
}
}
userModel in constructor must have it's type, but since my Schema was generated without using decorators (and my own classes), I can't use for example Model<User>, because User as class just doesn't exist here, so the question is:
Do I have to add separate User class with same fields as my Schema has, or there is a way to avoid it?

crud operation on json file without json server in Angular [duplicate]

I want to update my JSON file which I have placed in my assets folder, so If I am updating just one property of my JSON object so it should update that property only, without affecting any other properties value:
Let the sample code be :
loginInterface.ts
export interface loginModel {
Email: string;
Password: string;
}
login.component.ts
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '#angular/common/http'
import { loginModel } from './loginModel'
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
private _jsonURL = 'assets/Login.json';
private login: Array<loginModel>;
constructor(
private http: HttpClient) {
this.login = new Array<loginModel>();
}
ngOnInit() {
this.getLoginData();
}
getLoginData() {
this.http.get<loginModel[]>(this._jsonURL).subscribe(data => {
this.login = data;
console.log(this.login);
return this.login;
});
}
UpdateLoginData() {
// How to proceed on this one??
}
}
login.component.html
<div *ngFor = "let log of login">
{{log.Email}}
<input [ngModel]="log.Password">
</div>
<button (click)="UpdateLoginData()">Update</button>
This is just an example.
So if I am changing password at one place and clicking on update button , then it should update password of that specific Email only and I don't want to replace the whole file with new JSON object just for updating a single value, is this possible?
You can't do any file operation using just angular framework. You need server side implementation to achieve this. If you are not familiar with server side programming you can try using in memory angular database api.
https://www.npmjs.com/package/angular-in-memory-web-api
You can't change the content of JSON file directly through angular, you need the Backend in order to reflect the change on that JSON file.
No! You cannot change a file’s content using Angular. It is a file I/O operation that is handled by a backend framework/language (for example Node.JS) having file system API. You can create a RESTful API to modify the contents of the file and make an HTTP call from Angular.
In json server you can update using put method
//somewhat like given below
this.http.put(this._jsonURL+this.login[0].id,this.login[0]).subscribe();

NestJs: How to access database in entity listeners?

I've got a #BeforeInsert() listener in my Post entity. The listener is supposed to create a unique slug for the slug column before insertion.
For example:
export class Post extends BaseEntity {
#PrimaryGeneratedColumn()
id: number
#Column()
title: string
#Column()
slug: string
#BeforeInsert()
private updateSlug() {
this.slug = slugify(this.title)
// I will need to access the database to check whether the same slug has existsed already or not.
// How do I access the database in this listener method?
}
}
Since the slug column is supposed to be unique, I will have to check in the database to know whether the same slug already exists. If the slug already exists, I will then need to append a number behind the slug, like hello-word-1.
However, to do so, I will need to access the Post repository of the entity in the Post entity class before I can access the database. But I don't see how I can inject the repository into my Post entity class to access the database for this purpose.
How should I approach this problem?
As far as I know it's not possible to use dependency injection in typeorm entities, since they are not instantiated by nest. You can however use an EntitySubscriber instead which can inject dependencies. See the solution from this Github issue:
import { Injectable } from '#nestjs/common';
import { InjectConnection, InjectRepository } from '#nestjs/typeorm';
import { Connection, EntitySubscriberInterface, InsertEvent, Repository } from 'typeorm';
import { Post } from '../models';
#Injectable()
export class PostSubscriber implements EntitySubscriberInterface {
constructor(
#InjectConnection() readonly connection: Connection,
// Inject your repository here
#InjectRepository(Photo) private readonly postRepository: Repository<Post>,
) {
connection.subscribers.push(this);
}
listenTo() {
return Post;
}
beforeInsert(event: InsertEvent<Post>) {
// called before insert
};
}

Categories