Request provider in Nestjs, I cannot import REQUEST object - node.js

I am trying to implement a functionality with some request providers, I am following this example in the doc https://docs.nestjs.com/fundamentals/injection-scopes#request-provider
import { Injectable, Scope, Inject } from '#nestjs/common';
import { REQUEST } from '#nestjs/core';
import { Request } from 'express';
#Injectable({ scope: Scope.REQUEST })
export class CatsService {
constructor(#Inject(REQUEST) private readonly request: Request) {}
}
However, I cannot import the REQUEST object. It seems like it does not exist in the core of library
Does anyone know where is it?
These are my dependencies
"dependencies": {
"#nestjs/common": "^6.0.5",
"#nestjs/core": "^6.0.5",
Thanks

Related

Jest can't do imports outside module with "type":"module"

I am coding a Jest and ReactJS project and encountered a cannot use import statement outside a module error. I ran the command npm test. Here are the details:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import axios from './lib/axios.js';
^^^^^^
SyntaxError: Cannot use import statement outside a module
package.json:
{
"name": "frontend",
"version": "0.1.0",
"type": "module",
"private": true,
...
}
babel.config.cjs:
module.exports = {
presets:[
"#babel/preset-env",
["#babel/preset-react", {"runtime": "automatic"}]
]
}
Dashboard.test.js:
import { render, screen } from '#testing-library/react';
import Dashboard from '../src/components/Dashboard';
test('renders the landing page', () => {
render(<Dashboard />);
});
Dashboard.js:
import axios from 'axios';
import { useState, useEffect } from 'react';
import {useNavigate } from "react-router-dom";
import Cookies from 'universal-cookie';
const Dashboard = () => {
...
}
export default Dashboard;
I'd greatly appreciate any help you provide.

Not able to call node service from angular

I was learning to call node from angular,in my component i had the following code
import { Component, OnInit } from '#angular/core';
import {GetvalidationService} from '../_services/getvalidation.service';
#Component({
selector: 'app-content',
templateUrl: './content.component.html',
styleUrls: ['./content.component.css']
})
export class ContentComponent implements OnInit {
constructor(private service:GetvalidationService) { }
ngOnInit(): void {
this.getStudentData();
}
studentDetails :any =[]
getStudentData(){
this.service.getStudentData().subscribe()
}
}
the service is defined as followed
import { Injectable } from '#angular/core';
import {HttpClient} from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class GetvalidationService {
constructor(private http:HttpClient) { }
authenticateLogin(userDetails){
return this.http.post("/api/login",userDetails)
}
getStudentData(){
return this.http.get("/api/student");
}
}
and I have done the proxy.conf.json setting in package.json as well
my proxy.conf.json looks like
{
"/api/*":{
"target":"http://localhost:3000",
"secure": false,
"changeOrigin": true,
"pathrewrite":{"^/api":""}
}
}
inspite of this when i make a call for student the angular service makes call to http://localhost:4200/api/student instead of the node service on port 3000 where would i be going wrong ? I use npm run start to start the angular app
You have to define your baseUrl, if you do not do that then you end up with one you defined in your angular port options, i.e. localhost:4200.
So the piece of code required to connect to the node is this:
I suggest keeping the api url in environment, so that you can easily move it around different environments like this:
export const environment = {
production: false,
api: 'http://localhost:3000'
};
Your Service ts file will then include the api from enviornment:
import { Injectable } from '#angular/core';
import {HttpClient} from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class GetvalidationService {
private baseUrl= environment.api + '/api'; // URL to your web api
constructor(private http:HttpClient) { }
authenticateLogin(userDetails){
return this.http.post(`${this.baseUrl}/login`,userDetails)
}
getStudentData(){
return this.http.get(`${this.baseUrl}/student`);
}
}

Cannot read property 'encrypted' of undefined

I am trying to set up google oauth2 using Passportjs and NestJS(Fastify as underlying HTTP framework). I am not able to initialize google auth screen and the error comes up every time I try. I have tried a few different ways to do this, but there seems to be a problem with the AuthGuard and the code breaks every time on this step. I am sharing a snippet of the controller here which is handling the route for initializing the auth screen.
Here is the controller:
import { Controller, Get, Post, Body, UseGuards, Req, Res } from '#nestjs/common';
import { AuthGuard } from '#nestjs/passport';
#Controller('auth')
export class AuthController {
#Get('google')
#UseGuards(AuthGuard('google'))
intializeGoogleLogin() {}
}
The Google strategy:
import { Strategy } from 'passport-google-oauth2';
import { PassportStrategy } from '#nestjs/passport';
import { Injectable, UnauthorizedException } from '#nestjs/common';
#Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor() {
super({
clientID: <cleintId>,
clientSecret: <clientSecret>,
callbackURL: `/auth/google/callback`,
scope: ['profile', 'email'],
});
}
}
The module looks like this:
import { Module } from '#nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { GoogleStrategy } from './google.strategy';
#Module({
imports: [],
controllers: [AuthController],
providers: [AuthService, GoogleStrategy],
exports: [],
})
export class AuthModule {}
Dependencies
"#nestjs/common": "^7.0.0",
"#nestjs/core": "^7.0.0",
"#nestjs/passport": "^7.0.0",
"#nestjs/platform-fastify": "^7.0.5",
"#nestjs/typeorm": "^7.0.0",
"passport": "^0.4.1",
"passport-google-oauth2": "^0.2.0",
"passport-google-oauth20": "^2.0.0",
Soon realized that PassportJS is meant to work with only ExpressJS and since I am using Fastify as an underlying HTTP framework, it was acting in an unexpected way.
I so wish for PassportJS to make themselves compatible with other frameworks soon.

Nest can't resolve dependencies of the searchService (?). Please make sure that the argument at index

I am using Nestjs framework to develop my Elastic Service application.
I am using '#nestjs/elasticsearch' library inside my code and i am simply trying to establish database connection and use inside all other module. Please find my code example here.
My App Module looks below
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from './config/config.module';
import { DatabaseModule } from './database/database.module';
import { LayoutmgmtModule } from './layoutmgmt/layoutmgmt.module';
#Module({
imports: [ConfigModule,DatabaseModule, LayoutmgmtModule],
controllers: [AppController],
providers: [AppService]
})
export class AppModule {}
My Database Module is,
import { Module } from '#nestjs/common';
import { ElasticsearchModule } from '#nestjs/elasticsearch';
import {ConfigModule} from '../config/config.module';
import {ConfigService} from '../config/config.service';
import {DatabaseService} from './database.service';
#Module({
imports:[ElasticsearchModule.registerAsync({
imports:[ConfigModule],
useFactory: async (configService: ConfigService) => ({
host: configService.get('ELASTIC_URL'),
log: 'trace',
requestTimeout: 3000
}),
inject:[ConfigService]
})],
providers:[DatabaseService],
})
export class DatabaseModule {}
My Database Service is,
import { Injectable,HttpException } from '#nestjs/common';
import { ElasticsearchService } from '#nestjs/elasticsearch';
import { Client } from 'elasticsearch';
#Injectable()
export class DatabaseService {
private readonly esClient:Client;
constructor(private readonly elasticsearchService: ElasticsearchService) {
try {
this.esClient = elasticsearchService.getClient();
this.esClient.ping({ requestTimeout: 3000 },function(err,res,status){
if (err || !(res)) {
console.log('Unable to connect to the server. Please start the server. Error:', err);
throw new HttpException({
status: 'error',
message: 'Unable to connect to the server. Please start the server. Error:'
}, 500);
} else {
console.log('Connected to Server successfully!',res, status);
}
});
}
catch(err) {
console.log('Error in connection' + err);
throw new HttpException({
status: 'error',
message: 'Unable to reach Elasticsearch cluster'
}, 500);
}
}
}
Now Above i had initialized the connection and its getting connected to the database without issues, But i am trying to re-use ElasticsearchService in another module/service called layout module
Layout Module looks below
import { Module } from '#nestjs/common';
import { LayoutmgmtController } from './layoutmgmt.controller';
import { LayoutmgmtService } from './layoutmgmt.service';
#Module({
controllers: [LayoutmgmtController],
providers: [LayoutmgmtService],
})
export class LayoutmgmtModule {}
Layout Service Looks below
import { Inject, Injectable, Dependencies } from '#nestjs/common';
import { ElasticsearchService } from '#nestjs/elasticsearch';
import { Client } from 'elasticsearch';
#Injectable()
export class LayoutmgmtService {
private readonly esClient:Client;
constructor(#Inject(ElasticsearchService) private readonly elasticsearchService: ElasticsearchService) {
this.esClient = elasticsearchService.getClient();
if (!this.esClient){
console.log("Elastic alreayd connected")
}
}
}
If i use the ElasticSErachService in above service inside the constructor i am getting the below error, I wanted to reuse the existing connection ..
[Nest] 10724 - 10/14/2019, 4:50:41 PM [ExceptionHandler] Nest can't resolve dependencies of the LayoutmgmtService (?). Please make sure that the argument at index [0] is available in the LayoutmgmtModule context. +40ms
Error: Nest can't resolve dependencies of the LayoutmgmtService (?). Please make sure that the argument at index [0] is available in the LayoutmgmtModule context.
at Injector.lookupComponentInExports (C:\Subu\Elastic\elastic-nest-js\node_modules#nestjs\core\injector\injector.js:183:19)
at process._tickCallback (internal/process/next_tick.js:68:7)
at Function.Module.runMain (internal/modules/cjs/loader.js:744:11)
at Object. (C:\Subu\Elastic\elastic-nest-js\node_modules\ts-node\src\bin.ts:158:12)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
at Function.Module._load (internal/modules/cjs/loader.js:529:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
LayoutmgmtModule and DatabaseModule are not related anyway in your code.
You have registered the ElasticsearchModule in DatabaseModule but not in LayoutmgmtModule so it is unable to find the service.
Solution 1
You can get rid of the LayoutmgmtModule by just adding LayoutmgmtController and LayoutmgmtService in DataBaseModule and it should start working
Solution 2
You can make DataBaseModule as global by just adding #Global() before #Module decorator as mentioned here
You are not exporting ElasticsearchService anywhere. Perhaps your DatabaseModule should export it together with DatabaseService (LayoutmgmtService should use either of those).
On top of that, you should add given Service to providers of LayoutmgmtModule

TransferHttpCacheModule doesn't prevent duplicate HTTP Calls in Angular 8

I've set up an Angular 8 Project with Angular Universal. To prevent duplicate HTTP Calls, Angular offers TransferHttpCacheModule.
I followed the official Documentation to add TransferHttpCacheModule to Angular (https://github.com/angular/universal/blob/master/docs/transfer-http.md)
I also tried to add the BrowserTransferStateModule (https://www.twilio.com/blog/faster-javascript-web-apps-angular-universal-transferstate-api-watchdog), but this doesn't work either.
app.module.ts
import {BrowserModule} from '#angular/platform-browser';
import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';
import {TransferHttpCacheModule} from "#nguniversal/common";
#NgModule({
declarations: [
AppComponent,
...
],
imports: [
BrowserModule.withServerTransition({appId: 'serverApp'}),
TransferHttpCacheModule, // <-
...
HttpClientModule
]
bootstrap: [AppComponent]
})
export class AppModule {
}
app.server.module.ts
import {NgModule} from '#angular/core';
import {ServerModule, ServerTransferStateModule} from '#angular/platform-server';
import {AppModule} from './app.module';
import {AppComponent} from './app.component';
import {ModuleMapLoaderModule} from '#nguniversal/module-map-ngfactory-loader';
#NgModule({
imports: [
AppModule,
ServerModule,
ModuleMapLoaderModule,
ServerTransferStateModule // <-
],
bootstrap: [AppComponent],
})
export class AppServerModule {
}
main.ts
document.addEventListener('DOMContentLoaded', () => {
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
});
My Api Service
api.service.ts
import {Injectable} from '#angular/core';
import {HttpClient} from '#angular/common/http';
import {Observable} from "rxjs";
#Injectable({
providedIn: 'root'
})
export class ApiService {
private API_URL = '/api/';
constructor(private http: HttpClient) {
}
public get<T>(url: string): Observable<T> {
return this.http.get<T>(this.API_URL + url);
}
public post<T>(url: string, payload: T): Observable<T> {
return this.http.post<T>(this.API_URL + url, payload);
}
...
}
HTTP Call
home.component.ts
import {Component, OnInit} from '#angular/core';
import {ApiService} from "../../api.service";
import {Offer} from "../../offer-preview/offer.model";
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.sass']
})
export class HomeOffersComponent implements OnInit {
latestOffers: Offer[];
constructor(private apiService: ApiService) {
}
ngOnInit() {
this.apiService.get<Offer[]>("offer")
.subscribe(data => this.latestOffers = data);
}
}
According to the official TransferHttpCacheModule Docs, the Browser should not make an XHR to /api/offer, but the i see the XHR Call in the Developer Network Tools.
What am i doing wrong? Did I miss anything?
This is because of a mismatch between the absolute URLs the TransferHttpCacheModule is using as cache key for each request.
For example:
Server
Client
baseUrl
localhost:4200
domain.com
ressource
/api/people
/api/people
Absolute URL
http://localhost:4200/api/people
https://example.com/api/people
Only if both Absolute URLs are the same the request is successfully cached.
To circumvent this shortcoming you can implement your own caching via the BrowserTransferStateModule and Interceptors, e.g. as described here.
Just be sure to only use the relative URL:
const url = new URL(req.url);
const rel = url.toString().substring(url.origin.length);
this.transferState.set(makeStateKey(rel), event.body);

Resources