Use data accross all components - json

Created a component where I call all my api's. How do I use that data across all my other components
export let resultData = axios
.get(`https://swapi.dev/api/people/1`) //used a dummy api to test
.then(({ data }) => data);
export default class CacheService {
static myInstance = null;
result = resultData;
static getInstance() {
if (CacheService.myInstance == null) {
CacheService.myInstance = new CacheService();
}
return this.myInstance;
}
findAll() {
console.log(this.result);
return this.result;
}
}

You have created a promise and assigned to resultData variable but its not actually resolved.
Either you can use await or use then to get the data.
let testData = await newData.findAll();
or
newData.findAll().then((data)=>{
testData = data;
});

You need to await for the axios to resolve.
async findAll() {
const actualResult = await this.result;
console.log(actualResult);
return actualResult;
}

Related

Api call to json to interface to Mat-Tree

I'm running into issues with trying to convert a json response from an Api call into an interface that will be accepted by this buildFileTree. So the call is pulling from SQL, it is working in dapper, I also see the array of data in my webapp in my console. The issue is when I try to change the initialize() value for buildFileTree from my static json file 'SampleJson' (inside the project) to my new interface 'VehicleCatalogMod' the tree shows up with SampleJson but when I switch the data to VehicleCatalogMod, the tree collapses.
dataStoreNew: VehicleCatalogMod[] = [];
constructor(private _servicesService: ServicesService){
this._servicesService.GetVehicleCat()
.subscribe(data => {
this.dataStoreNew = [];
this.dataStoreNew = data;
console.log(data);
})
this.initialize();
}
initialize() {
this.treeData = SampleJson;
// Working as SampleJson this is where the problem happens
const data = this.buildFileTree(VehicleCatalogMod, 0);
console.log(data);
this.dataChange.next(data);
}
buildFileTree(obj: object, level: number): TodoItemNode[] {
return Object.keys(obj).reduce<TodoItemNode[]>((accumulator, key) => {
let value = obj[key];
const node = new TodoItemNode();
node.item = key;
if (value != null) {
if (typeof value === 'object') {
node.children = this.buildFileTree(value, level + 1);
} else {
node.item = value;
}
}
return accumulator.concat(node);
}, []);
}
GetVehicleCat(): Observable<any> {
console.log('Vehicle Catalog got called');
return this.http.get('https://api/right/here',
{ headers: this.options.headers });
}
I tried a multitude of different things to try & get this working. I'm pretty much stagnated. Same error occurs when I try this.dataStoreNew instead. No errors in console, it literally just collapses the tree into one non distinguishable line. Also when I used: const vcm = new VehicleCatalogMod(); it made the tree pop up with the different properties but not the API values.
I also attached an image of the HTML element that appears.
with VehicleCatalogMod
with SampleJson

TypeScript correctly type a queryresult MySQL

I am using the mysql2/promise npm package for connecting and doing queries to a MySQL database. I got confused trying to set the correct typing for my query result, because I don't know in advance what type the result will be.
I have created a database class that has an async query method.
// Database.ts
import mysql, { Pool } from "mysql2/promise"; // import mysql2/promise
export class Database implements IDatabase {
logger: ILogger;
pool: Pool;
constructor(logger: ILogger) {
this.logger = logger;
// pool connection is set up here
}
async query(sql: string, options?: unknown): Promise<unknown> { // type?
const [rows] = await this.pool.query(sql, options);
return rows;
}
}
In my server code, I would like to be able do something like this:
// server.ts
import { Database } from "./core/Database";
const db = new Database(logger);
app.get("/", async (req, res) => {
const sql = `
select *
from users;
`;
const users: IUser[] = await db.query(sql); // get people
// do some logic x
// send response
res.json({
result: x
});
});
Using unknown doesn't work because I can't assign it to my type, using any does, but feels wrong. Is there a clean way to do this?
Type the function as:
async query<T = unknown>(sql: string, options?: unknown): Promise<T[]> {
Then use the function this way:
const users = await db.query<IUser>(sql);
With help of #Evert and this answer, I found a solution
I created following types:
export type DbDefaults = RowDataPacket[] | RowDataPacket[][] | OkPacket[] | OkPacket;
export type DbQueryResult<T> = T & DbDefaults;
Rewrote my method like this:
async query<T>(sql: string, options?: unknown): Promise<DbQueryResult<T[]>> {
const [result] = await this.pool.query<DbQueryResult<T[]>>(sql, options);
return result;
}
I can use it like this now:
const sql = `
select *
from users;
`;
const people = await db.query<IUser>(sql);
Just casting as T is also possible.
public async query<T>(sql: QueryString, parameters?: unknown[]): Promise<T[]> {
const [rows] = await this.pool.query(sql, parameters);
return rows as T[];
}

how to access a function in a promise

my code in react application
I have I class:
class SampleModuleController{
getSampleModuleSheet()
{
console.log("getSampleModuleSheet");
return tableSheet;
}
retrivePageData(pageNumber,pageLength){
console.log("retrivePageData calledd");
let pageData= asyncAwaitService.findTablePageTestData(pageNumber,pageLength);
return pageData;
}
}
export let sampleModuleController = new SampleModuleController();
SampleModuleController class lazy loaded and its getSampleModuleSheet method can use successfully.
in jsx:
<DataTable getPageData={import('../controllers/sampleModuleContrller').then(({sampleModuleController}) => {return sampleModuleController.retrivePageData;})} />
in js file:
async newPageManager(){
console.debug("this.props.getPageData------",this.props.getPageData);
let pageData = await props.getPageData(1,34);
}
out put
so how can I call the fuction inside the promise
in your jsx, it's apparent that the promise returns a method delegate.
So, this.props.getPageData when resolved with await will result in a method delegate that is itself to be invoked on.
we'll modify your snippet as followed;
async newPageManager(){
console.debug("this.props.getPageData------",this.props.getPageData);
let getPageData = await props.getPageData;
let pageData = getPageData(1,34);
}
additionally, since props.getPageData is returning a promise, it is thenable.
so, you could pass the result of that promise into a then function scope -- something like the following
async newPageManager(){
console.debug("this.props.getPageData------",this.props.getPageData);
let getFirstPagePromise = props.getPageData.then((fn) => fn.bind(this, 1, 32));
let getFirstPage = await getFirstPagePromise;
let pageData = getFirstPage();
}

Node.js decrypting encrypted string from MySQL causes EVP_DecryptFinal_ex:wrong final block length

I have 2 functions in an encryption service class. 1 to encrypt data, and 1 to decrypt data.
export default class EncryptionService {
private static algorithm = 'aes-256-cbc';
private static key = createHash('sha256').update(String('keyString')).digest('base64').substr(0, 32);
private static iv = Buffer.from('ivString');
public static encryptData(data: string): string {
const cipher = createCipheriv(this.algorithm, this.key, this.iv);
let encrypted = cipher.update(data);
encrypted = Buffer.concat([encrypted, cipher.final()]);
const encryptedStr = encrypted.toString('base64');
console.log('encryptedStr: ' + encryptedStr);
return encryptedStr;
}
public static decryptData(data: string): string {
const decipher = createDecipheriv(this.algorithm, this.key, this.iv);
const decrypted = decipher.update(data, 'base64');
const decryptedData = Buffer.concat([decrypted, decipher.final()]).toString();
console.log('decryptedData: ' + decryptedData);
return decryptedData;
}
}
In my controller, when I call the encryptData function then immediately call the decryptData function, passing in the encrypted data returned from the encryptData function, I get the correct unencrypted string back.
import EncryptionService from '../services/encryption-service';
export default class MyController {
public async postData(request: Request, response: Response) {
const encryptedAudioFileName = EncryptionService.encryptData(request.body.audio_file_name);
EncryptionService.decryptData(encryptedAudioFileName);
}
}
However - when I store the encrypted Data returned from encryptData into mySQL via a post function in the controller and then attempt to decrypt the data retrieved from mySQL via a get function in the controller, an error occurs in the decryptData function stating "EVP_DecryptFinal_ex:wrong final block length".
public async postData(request: Request, response: Response) {
Logger.info(request, response, 'Request Received');
try {
if (request.body) {
const dataEntity = new dataEntity();
dataEntity.audio_file_name = EncryptionService.encryptData(request.body.audio_file_name);
const result = await getManager().save<dataEntity>(dataEntity);
if (result) {
const responseObject = {
timestamp: new Date().toUTCString(),
method: request.method,
status: 'Success',
statusCode: 201,
message: 'successfully created.',
path: request.originalUrl,
reference: result.id,
};
Logger.success(request, response, responseObject);
response.status(201).json(responseObject);
} else {
response.status(400).json(
ResponseService.badRequestErrorResponseObject(request, response));
}
} else {
response.status(400).json(
ResponseService.badRequestErrorResponseObject(request, response, 'Body is invalid'));
}
} catch (error) {
response.status(500).json(
ResponseService.internalErrorResponseObject(request, response, error));
}
}
public async getData(request: Request, response: Response) {
Logger.info(request, response, 'Request Received');
try {
const allData: dataEntity[] =
await getConnectionManager().get().getRepository(dataEntity).find();
if (allData) {
const entityResponseArray = [] as object[];
allData.forEach( (entity) => {
const dataResponse = {} as {id: number, audioFileName: string};
dataResponse.id = entity.id!;
dataResponse.audioFileName = EncryptionService.decryptData(entity.audio_file_name!);
entityResponseArray.push(dataResponse);
});
Logger.success(request, response, 'Get list of data');
response.json(entityResponseArray);
} else {
response.status(404).json(
ResponseService.notFoundErrorResponseObject(request, response));
return;
}
} catch (error) {
response.status(500).json(
ResponseService.internalErrorResponseObject(request, response, error));
}
}
It happens at this line in decryptData:
const decryptedData = Buffer.concat([decrypted, decipher.final()]).toString();
What am I doing incorrectly?
The issue was my column length and or type. The encrypt and decrypt code works fine. The data returning from mysql was being cut off so it couldn't decrypt properly. Stupid mistake. Thanks for the insight.

Access the common method from other component

Here I am using some method for frequently used methods in common method ts file. If I am going to access these method I got null values Please help me out.
CommonMethod.ts:
GetCategoryList(){
let Mylist = [];
this.auth.Get("Master/Category").then((user) => {
Mylist= user.json();
});
return Mylist;
}
My Another component:
I am trying to access common method ts file here. by below way.
import {CommonMethod} from './CommonMethod';
...
...
construtor(private com:CommonMethod){}
ngOninit(){
console.log(this.com.GetCategoryList());
}
this.auth.Get is going to be async in nature due to which the return MyList line will get called even before the callback to the then method is called and the data is arrived and set in MyList.
You can use the async await syntax to fix it:
async GetCategoryList() {
let Mylist = [];
const user = await this.auth.Get("Master/Category");
Mylist = user.json();
return Mylist;
}
You can then use it like this in your Component:
import {CommonMethod} from './CommonMethod';
...
...
construtor(private com: CommonMethod) {}
async ngOninit() {
const myList = await this.com.GetCategoryList();
console.log(myList);
}
PS: Make sure that CommonMethod is a service and is added to the providers array of your #NgModule
Should update your common method:
GetCategoryList(): Promise<any>{
let Mylist = [];
return this.auth.Get("Master/Category").then((user) => {
Mylist= user.json();
Promise.resolve(Mylist);
});
}
And
ngOninit(){
this.com.GetCategoryList().then(results=>{
console.log(results);
});
}