why fresh-tabula-js not working with nestJs? - nestjs

Getting errors while using fresh-tabula-js with nestJs.
Express server
import Tabula from "fresh-tabula-js";
const table = new Tabula("t5.pdf", { spreadsheet: true });
console.log(table.extractCsv().output);
NestJS
1) code-1
import { Injectable } from '#nestjs/common';
import Tabula = require('fresh-tabula-js');
#Injectable()
export class PdfExtractorService {
tabula: Tabula;
constructor() {
this.tabula = new Tabula('t5.pdf', { spreadsheet: true });
}
extractPdfToJson() {
const data: Promise<{ output: string; error: string }> =
this.tabula.getData();
console.log(data);
}
}
Error:
this.tabula.getData is not a function
2) code-2
import { Injectable } from '#nestjs/common';
import Tabula = require('fresh-tabula-js');
#Injectable()
export class PdfExtractorService {
tabula: Tabula;
constructor() {
this.tabula = new Tabula('t5.pdf', { spreadsheet: true });
}
extractPdfToJson() {
const data: Promise<{ output: string; error: string }> =
this.tabula.extractCsv().output;
console.log(data);
}
}
Error:
error TS2339: Property 'extractCsv' does not exist on type 'Tabula'.
this.tabula.extractCsv().output;
Tried all possible ways but it is not working with nestJs however it is working with expressJs.
How to make it run in nestJS?

Related

Error injecting dependency into controller with tsyringe

I am using express and tsyringe for dependency injections.
When I try to use the service dependency on my controller I get an error UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'addressService' of undefined in file addressController.ts
I've searched for several videos and articles and I couldn't find a way to solve them. I will leave my code below
addressRepository.ts
import { AddressResponseDTO } from '../../dtos/response/address/addressResponseDTO';
export interface IAddressRepository {
getAddresses(): Array<AddressResponseDTO>;
}
addressRepositoryImpl.ts
import { AddressResponseDTO } from '../../dtos/response/address/addressResponseDTO';
import { IAddressRepository } from '../declarations/addressRepository';
export default class AddressRepositoryImpl implements IAddressRepository {
getAddresses(): Array<AddressResponseDTO> {
const address1: AddressResponseDTO = {
id: 'ADR123',
postalCode: '17014273',
address: 'Rua José Aiello',
district: 'Centro',
number: '347',
city: 'Bauru',
state: 'São Paulo',
phoneNumber: '16997102842',
clientName: 'João Mário Marcelo Campos',
};
const address2: AddressResponseDTO = {
id: 'ADR456',
postalCode: '07135290',
address: 'Rua Mariano Moya Peramos',
district: 'Jardim Adriana',
number: '1103',
city: 'Guarulhos',
state: 'São Paulo',
phoneNumber: '16997102842',
clientName: 'João Mário Marcelo Campos',
};
return [address1, address2];
}
}
addressService.ts
import { AddressResponseDTO } from '../../dtos/response/address/addressResponseDTO';
import ResultResponseDTO from '../../dtos/response/resultResponseDTO';
export interface IAddressService {
getAddresses(): ResultResponseDTO<Array<AddressResponseDTO>>;
}
addressServiceImpl.ts
import { StatusCodes } from 'http-status-codes';
import { inject, injectable } from 'tsyringe';
import logger from '../../configurations/logger';
import { AddressResponseDTO } from '../../dtos/response/address/addressResponseDTO';
import ResultResponseDTO from '../../dtos/response/resultResponseDTO';
import { IAddressRepository } from '../../repositories/declarations/addressRepository';
import { IAddressService } from '../declarations/addressService';
#injectable()
export default class AddressServiceImpl implements IAddressService {
private addressRepository: IAddressRepository;
constructor(#inject('AddressRepository') addressRepository: IAddressRepository) {
this.addressRepository = addressRepository;
}
getAddresses(): ResultResponseDTO<AddressResponseDTO[]> {
try {
logger.info('AddressService.getAddresses - start');
const addresses = this.addressRepository.getAddresses();
logger.info('AddressService.getAddresses - end');
return ResultResponseDTO.ok(StatusCodes.OK, '', addresses);
} catch (error) {
logger.error(`AddressService.getAddresses - error - message ${error}`);
return ResultResponseDTO.fail(
StatusCodes.INTERNAL_SERVER_ERROR,
'Error getting addresses',
error,
);
}
}
}
addressController.ts
Error at line: const result = this.addressService.getAddresses();
import { Request, Response } from 'express';
import { inject, injectable } from 'tsyringe';
import { IAddressService } from '../services/declarations/addressService';
#injectable()
export class AddressController {
constructor(#inject('AddressService') private addressService: IAddressService) {}
public async getAddresses(request: Request, response: Response): Promise<Response> {
const result = this.addressService.getAddresses();
return response.status(result.httpStatus).json(result.getResponse());
}
}
routes.ts
import { Router } from 'express';
import { container } from 'tsyringe';
import { AddressController } from './controllers/addressController';
import AddressRepositoryImpl from './repositories/implementations/addressRepositoryImpl';
import AddressServiceImpl from './services/implementations/addressServiceImpl';
const routes = Router();
container
.register('AddressRepository', {
useClass: AddressRepositoryImpl,
})
.resolve(AddressRepositoryImpl);
container
.register('AddressService', {
useClass: AddressServiceImpl,
})
.resolve(AddressServiceImpl);
const addressController = container.resolve(AddressController);
routes.get('/', (request, response) => {
response.send('It works!');
});
// AddressController
routes.route('/v1/address').get(addressController.getAddresses);
export default routes;
You register service inside IoC as 'AddressServiceImpl' and after that try to call to it as 'AddressService'.
// service file
#injectable()
export default class AddressServiceImpl implements IAddressService {
...
// controller file
#injectable()
export class AddressController {
constructor(#inject('AddressService') private addressService: IAddressService) {}

How can i asynchronouslycall this service function in another component? Angular 11

I have an async function getIdentByInfo and in the console i get the right output if i log it in this function. As soon as i call it in another component it doesnt work and i only get 'undefined'. I know it has something to do with beeing ssynchrone and Promises but i cant figure out how to solve my issue. I need the Model class filled with attributes coming from the http request in another component to send them to another service
import { EventEmitter, Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { IdentModel } from "../models/identmodel.model";
import { IdentteilComponent } from "../pages/identteil/identteil.component";
#Injectable({
providedIn: 'root',
})
export class InfoWebservice {
url = 'http://localhost:4201';
ident: IdentModel[];
constructor(private http: HttpClient) { }
// promise vom typ IdentModel zurückgeben
getIdentByInfo(id: string, vwk: string) {
this.http.get(this.url).toPromise().then(data => {
for (let i in data){
this.ident.push(data[i])
if ( this.ident[i].identNr == id && this.ident[i].vwk == vwk){
return this.ident[i];
}
}
});
}
}
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { InfoWebservice } from '../../webservices/info.webservice'
import { ImageWebservice } from '../../webservices/image.webservice'
import { IdentModel } from "../../models/identmodel.model";
#Component({
selector: 'app-identteil',
templateUrl: './identteil.component.html',
styleUrls: ['./identteil.component.scss']
})
export class IdentteilComponent implements OnInit {
ident = [];
identNr:string;
vwk:string;
imgFrontLink:string;
imgBackLink:string;
constructor(private router: Router, private service: InfoWebservice, private image: ImageWebservice) { }
getIdentNr() : string {
var split = this.router.url.split("/");
this.identNr = split[2];
return this.identNr;
}
//return type is STRING
getVwk() {
// output von window.location.host = repapp-maw.dbl.de
// var splitHost = window.location.host.split(".");
var splitHost = 'repapp-maw';
var splitV = splitHost.split("-");
this.vwk = splitV[1];
return this.vwk;
}
callInfoService = async () => {
return await this.service.getIdentByInfo(this.getIdentNr(), this.getVwk());
}
ngOnInit() {
console.log(this.callInfoService());
}
}
When you use angular, its always preferred not to use await/Promise. Angular has an in-built RX-JS library which has tonnes of super-awesome functionalities that you can use.
For Example, in your case, you can do something like this:
// Your Service File can make use of 'Behavior Subject'
// Please read more about it here: https://www.learnrxjs.io/learn-rxjs/subjects/behaviorsubject
import { EventEmitter, Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { IdentModel } from "../models/identmodel.model";
import { IdentteilComponent } from "../pages/identteil/identteil.component";
#Injectable({
providedIn: 'root',
})
export class InfoWebservice {
url = 'http://localhost:4201';
ident: IdentModel[];
initialIdentValues: IdentModel = [];
private identSource: BehaviorSubject<IdentModel[]> = new BehaviorSubject<IdentModel[]>(this.initialIdentValues);
public identValuesObs$: Observable<IdentModel[]> = this.identSource.asObservable();
// Create a method to set the values in component-1
setIdentValues(identValues: IdentModel[]) {
this.identSource.next(identValues);
}
// Create a method to return values in component-2 or any component
returnIdentValues() {
return this.identValuesObs$;
}
constructor(private http: HttpClient) { }
// Change your service call to this:
getIdentByInfo(id: string, vwk: string): Observable<any> {
return this.http.get(this.url);
}
}
Now in your component-1 where you want to set the values of this identvalues:
// Component-1
constructor(private infoWebService: InfoWebService){}
// Create a method where you get the values
someMethod() {
// Call the API method here and subscribe and then set the values
this.infoWebService.getIdentInfoById(id, vwk).subscribe((data: any) => {
// Your logic goes here ANDD
if (data) {
for (let i in data){
this.ident.push(data[i])
let localIdentsWithRequiredLogic = [];
if ( this.ident[i].identNr == id && this.ident[i].vwk == vwk){
localIdentsWithRequiredLogic.push(this.ident[i]);
}
// THIS IS IMPORTANT
this.infoWebService.setIdentValues(localIdentsWithRequiredLogic);
}
}
})
}
Then in component-2 or whatever component you want, you can retrieve it using the returnIdentValues method like this:
// In component-2
inSomeMethodWhereYouRequireIdentValues() {
this.infoWebService.returnIdentValues().subscribe(data => {
console.log(data) // this is data that you set in component one
})
}

NestJS testing with Jest custom repository (CassandraDB)

The code I am trying to test the driver / repository for my nodeJS project:
import { Injectable, OnModuleInit } from '#nestjs/common';
import { mapping, types } from 'cassandra-driver';
import { Products } from './poducts.model';
import { CassandraService } from '../database/cassandra/cassandra.service';
import Uuid = types.Uuid;
#Injectable()
export class ProductsRepository implements OnModuleInit {
constructor(private cassandraService: CassandraService) {}
productsMapper: mapping.ModelMapper<Products>;
onModuleInit() {
const mappingOptions: mapping.MappingOptions = {
models: {
Products: {
tables: ['products'],
mappings: new mapping.UnderscoreCqlToCamelCaseMappings(),
},
},
};
this.productsMapper = this.cassandraService
.createMapper(mappingOptions)
.forModel('Products');
}
async getProducts() {
return (await this.productsMapper.findAll()).toArray(); // <-----Breaks here with findAll()
}
}
I am trying to write something like this:
describe('product repository get all', () => {
it('calls the repository get all', async () => {
const await productsRepository.getProducts();
expect().DoSomething()
});
});
This is the error I am getting:
Cannot read property 'findAll' of undefined
How would I accomplish a meaning-full test with Jest to get proper code coverage?
When I try to use jest to spy on the this.products.Mapper.findAll() it seems to break every time.

Inversify - Nodejs- Container binding results in max call size exceeded

I am trying to use inversify for DI injection in a small project in typescript. I wanted to create a logging middleware that logs every request with a pino logger customized. I did establish the dependencies manually when the app is created but was wooed by inversify and wanted to try it out.
But I am stuck and unable to proceed. THis is the error that I am facing. Not sure what is making the call to exceed the stack size. Please help me out
public set app_port(app_port: number) {
^
RangeError: Maximum call stack size exceeded
PinoLoggingService.ts
import * as pino from 'pino';
import * as os from 'os';
import * as momentTimeZone from 'moment-timezone';
import { DEFAULT_TIMEZONE, DEFAULT_TIME_FORMAT } from '../../shared/constants/app.constants';
import { AppConfigModel } from './../../shared/model/app.config.model';
import { isNullOrUndefined } from 'util';
import httpContext = require('express-http-context');
import { injectable, inject } from 'inversify';
import { TYPES } from '../../shared/constants/app.types';
import { AppConfigService } from '../../shared/service/app.config.service';
#injectable()
export class PinoLoggingService {
private appConfig: AppConfigModel;
constructor(#inject(TYPES.AppConfigService) private appConfigService: AppConfigService){
this.appConfig = appConfigService.appConfigModel;
}
private getTimeStamp(){
return momentTimeZone().tz(DEFAULT_TIMEZONE).format(DEFAULT_TIME_FORMAT);
}
public infoLogService (fileName): pino.Logger {
return pino({
level: 'info',
name: this.appConfig.app_name,
messageKey: 'feedback-Logs',
base: {pid: process.pid, hostname: os.hostname,
timestamp: this.getTimeStamp(),
appName: this.appConfig.app_name,
fileName: fileName,
request_id: isNullOrUndefined(httpContext.get('reqId')) ? 'Not an actual request ' : httpContext.get('reqId')
},
enabled: true,
useLevelLabels: true,
});
}
}
my AppConfigService.ts - AppConfigModel is just a plain ts with getters and setters.
#injectable()
export class AppConfigService implements IAppConfigService{
private appModel: AppConfigModel;
constructor() {
console.log('parg is:'+path.resolve(__dirname));
}
public get appConfigModel(): AppConfigModel {
if(isNullOrUndefined(this.appModel)) {
this.appModel = new AppConfigModel();
this.appModel.app_port = isNullOrUndefined(process.env.PORT) ? DEFAULT_PORT : parseInt(process.env.PORT);
this.appModel.app_lcp = process.env.LCP;
this.appModel.app_name = process.env.APP_NAME;
this.appModel.app_host = process.env.HOST;
this.appModel.app_node_env = process.env.NODE_ENV;
this.appModel.app_logging = JSON.parse (process.env.PINO_ENABLE_LOGGING);
this.appModel.app_version = process.env.VERSION;
this.appModel.app_context_path = process.env.CONTEXT_PATH;
}
return this.appModel;;
}
}
This is my loggingMiddleware.ts
import * as express from 'express';
import { AppUtilService } from './../util/app.util.service';
import { file } from '#babel/types';
import { inject, injectable } from 'inversify';
import { TYPES } from '../constants/app.types';
import { PinoLoggingService } from '../../logging/service/logging.service';
interface ILoggingMiddleware {
loggingMiddlewareMethod () : express.Router;
}
#injectable()
export class LoggingMiddleware implements ILoggingMiddleware {
constructor(#inject(TYPES.AppUtilService) private utilService: AppUtilService,
#inject(TYPES.PinoLoggingService) private pinoLoggingService: PinoLoggingService){
}
public loggingMiddlewareMethod() {
const appRouter = express.Router();
return appRouter.use((req:express.Request, res:express.Response, next) => {
const fileName = this.utilService.getFileName(__filename);
this.pinoLoggingService.infoLogService(fileName).info('req.url:', req.url);
this.pinoLoggingService.infoLogService(fileName).info('req.headers:', req.headers);
this.pinoLoggingService.infoLogService(fileName).info('req.body:', req.body);
next();
});
}
}
THis is my request tracing middleware
const httpContext = require('express-http-context');
import * as express from 'express';
import { injectable } from 'inversify';
#injectable()
export class RequestTracerMiddleware {
public requestTracer() {
const app = express();
app.use(httpContext.middleware);
}
}
THis is my inversify config
import { Container } from "inversify";
import { TYPES } from "./module/shared/constants/app.types";
import { AppConfigService } from "./module/shared/service/app.config.service";
import { AppUtilService } from "./module/shared/util/app.util.service";
import { LoggingMiddleware } from "./module/shared/middlewares/logging.middleware";
import { CommonMiddleware } from "./module/shared/middlewares/common.middlewares";
import { RequestTracerMiddleware } from "./module/shared/middlewares/request.tracer.middleware";
import { PinoLoggingService } from "./module/logging/service/logging.service";
import { StudentController } from "./module/shared/test.controller";
const DIContainer = new Container({defaultScope: "Singleton"});
DIContainer.bind<AppConfigService>(TYPES.AppConfigService).to(AppConfigService);
DIContainer.bind<AppUtilService>(TYPES.AppUtilService).to(AppUtilService);
DIContainer.bind<LoggingMiddleware>(TYPES.LoggingMiddleware).to(LoggingMiddleware);
DIContainer.bind<CommonMiddleware>(TYPES.CommonMiddleware).to(CommonMiddleware);
DIContainer.bind<RequestTracerMiddleware>(TYPES.RequestTracerMiddleware).to(RequestTracerMiddleware);
DIContainer.bind<PinoLoggingService>(TYPES.PinoLoggingService).to(PinoLoggingService);
DIContainer.bind<StudentController>(TYPES.StudentController).to(StudentController);
export default DIContainer;
This is my server.ts
import 'reflect-metadata';
import * as DIContainer from './inversify.config';
import {InversifyExpressServer } from 'inversify-express-utils'
import { inject } from 'inversify';
import { TYPES } from './module/shared/constants/app.types';
import { CommonMiddleware } from './module/shared/middlewares/common.middlewares';
import { LoggingMiddleware } from './module/shared/middlewares/logging.middleware';
import { RequestTracerMiddleware } from './module/shared/middlewares/request.tracer.middleware';
const container = DIContainer.default;
let server = new InversifyExpressServer(container);
const commMiddleware = container.resolve(CommonMiddleware);
// const requestTracingMiddleware = container.resolve(RequestTracerMiddleware);
const loggingMiddleware = container.resolve(LoggingMiddleware);
server.setConfig(appRouter => {
appRouter.use(commMiddleware.enableBodyParser());
appRouter.use(loggingMiddleware.loggingMiddlewareMethod());
});
// set errorConfig if needed
const app = server.build();
app.listen(2000, () => {
console.log('listening to port');
});
This is a sample controller that I setup.
import {controller, httpGet, httpPost, requestHeaders, requestParam, BaseHttpController, HttpResponseMessage, StringContent} from 'inversify-express-utils';
#controller("/IStudentController")
export class StudentController extends BaseHttpController {
constructor( ) {
super();
console.log('value of stdservuce:');
}
#httpGet("/Iget")
public getStudentDetails(#requestHeaders() reqHeaders: string[] ) {
// sample returning json resuilt - IHttpAcctionResults
const val = 43;
console.log('val from the servuc:', val);
return this.json(val, 200);
}
}

How can i fix .take() operator and preserve snapshot || Angular , Ionic 3

I have a problem in .take() operator after they change to AngulaFireObject
and preserveSnapshot.
What can be the problem?
import { Injectable } from '#angular/core';
import { AngularFireDatabase, AngularFireObject } from 'angularfire2/database';
import { User } from 'firebase/app';
import { Profile } from '../../models/profile/profile.interface';
import { Observable } from 'rxjs/observable';
import { take } from 'rxjs/operator/take';
#Injectable()
export class DataService {
profileObject : AngularFireObject<Profile>
constructor(private database: AngularFireDatabase) {
}
getProfile(user: User) {
this.profileObject = this.database.object(`/profiles/${user.uid}`, { preserveSnapshot: true }); <<<in here
return this.profileObject.take(1); <<<< and here
}
async saveProfile(user: User, profile: Profile) {
this.profileObject = this.database.object(`/profiles/${user.uid}`);
When I run my app with ionic serve it gives me this
Typescript Error Expected 1 arguments, but got 2. C:/Users/A7MD/Desktop/WallPapa/src/providers/data/data.service.ts getProfile(user: User) { this.profileObject = this.database.object(/profiles/${user.uid}, { preserveSnapshot: true }); –
and
Typescript Error Property 'take' does not exist on type 'AngularFireObject<Profile>'. C:/Users/A7MD/Desktop/WallPapa/src/providers/data/data.service.ts return this.profileObject.take(1); }
You can see the photo here:

Resources