How to work around the require(“../../../../../../../”) frustration In NodeJS? - node.js

Any better ways of solving this kind of problem in node.js below?
import foo from "../../../modules/home/models/index.js"
import bar from "../../../modules/about/models/index.js"
import baz from "../../../modules/contact/models/index.js"
At least making them into something like this?
import foo from "/home/models/index.js"
import bar from "/about/models/index.js"
import baz from "/contact/models/index.js"
Any ideas?

You need inversion of control.
./modules/home/index.js
const homeModel1 = () => {
//...
}
const homeModel2 = () => {
//...
}
module.exports = Object.assign({}, { homeModel1, homeModel2 })
1. An object will be exported of the following shape:
{
homeModel1: () => {},
homeModel2: () => {}
}
2. When you add a new model, simply add it or import it into this file and then add it to the export object.
./modules/index.js
import { homeModels } from './modules/home'
import { aboutModels } from './modules/about'
import { contactModels } from './modules/contact'
module.exports = Object.assign({}, { homeModels, aboutModels, contactModels })
The models are destructured out and then exported as methods on a new object.
Likewise, same shape object is exported with all your models cultivated together, bringing all their dependencies with them.
somewhere else
import modules from './modules'
const query = modules.homeModels.homeModel1()
Bonus:
To clarify, Object.assign({}, obj1, obj2) creates a new object with the prototype set to the Object prototype, and merges the properties and methods of obj1 and obj2. In this simple form, it is essentially the same as const obj = {}.
A bit more advanced, is Object.assign({}, { obj1, obj2 }) which makes obj1 and obj2 properties on the new object. You can do some simple testing to get a feel for the data structures.
We also used some destructuring. If you are having issues getting things lined up properly, you should look at those aspects plus how you are importing them into a file. For example, import obj1 from './modules' will bring the entire object in from ./modules, but import { obj1 } from './modules' will destructure obj1 from the object that it pulls in, so obj1 was a method/property of the object.
Do some research into inversion of control and dependency injection.

Related

How to determine if "click" or "box-select" was used with Streamlit/Plotly to return data from chart to Streamlit

I'm not a Javascript/Typescript/React dev. I'm hacking my way through this for a work project.
I'm using Streamlit, with plotly.
I'm hacking the basic code from streamlit-plotly-events.
I was trying to have the click or box-select information passed back with the data selected via the plotlyEventHandler() (see code below.) However, both this.props.args["click_event"] and this.props.args["select_event"] are true, regardless of whether you use box-select in the plotly chart, or click a single data point in the chart.
I thought of assuming if there is only one data point, then it was a click - but you can box select only one data point.
// import React, {useState,useEffect} from "react"
import React, { ReactNode } from "react"
//import React from "react"
import {
StreamlitComponentBase,
withStreamlitConnection,
Streamlit,
// ComponentProps,
} from "streamlit-component-lib"
import Plot from "react-plotly.js"
class StreamlitPlotlyEventsCapture extends StreamlitComponentBase {
public render = (): ReactNode => {
// Pull Plotly object from args and parse
const plot_obj = JSON.parse(this.props.args["plot_obj"]);
const override_height = this.props.args["override_height"];
const override_width = this.props.args["override_width"];
// Event booleans
const click_event = this.props.args["click_event"];
const select_event = this.props.args["select_event"];
const hover_event = this.props.args["hover_event"];
Streamlit.setFrameHeight(override_height);
return (
<Plot
data={plot_obj.data}
layout={plot_obj.layout}
config={plot_obj.config}
frames={plot_obj.frames}
onClick={click_event ? this.plotlyEventHandler : function(){}}
onSelected={select_event ? this.plotlyEventHandler : function(){}}
onHover={hover_event ? this.plotlyEventHandler : function(){}}
style={{width: override_width, height: override_height}}
className="stPlotlyChart"
/>
)
}
/** Click handler for plot. */
private plotlyEventHandler = (data: any) => {
// Build array of points to return
var clickedPoints: Array<any> = [];
//const util = require('util')//#33333 used with util.inspect(arrayItem) below
// I dont know why we can't directly use "this.variables" in the clickedPoints.push
// but we can't, so we create the variables here.
var wasClicked = this.props.args["click_event"];
var wasSelected = this.props.args["select_event"];
var wasHovered = this.props.args["hover_event"];
data.points.forEach(function (arrayItem: any) {
// console.log(util.inspect(arrayItem, {maxArrayLength: null, depth:null }))
clickedPoints.push({
// I dont know why we can't directly use "this.variables" here, but we can't
// so we use the variables created above.
clicked:wasClicked,
selected:wasSelected,
hovered:wasHovered,
x: arrayItem.x,
y: arrayItem.y,
curveNumber: arrayItem.curveNumber,
pointNumber: arrayItem.pointNumber,
pointIndex: arrayItem.pointIndex
})
});
// Return array as JSON to Streamlit
Streamlit.setComponentValue(JSON.stringify(clickedPoints))
}
}
export default withStreamlitConnection(StreamlitPlotlyEventsCapture)

How can I call a function of an exported function of a module in another script? NodeJS

I want to use a function, which is inside another function (function2) in another js file (2nd.js).
My current code looks something like this:
1st.js
module.exports = {
function1(){
function2(){
//...
}
}
}
2nd.js
const { function2 } = require("1st.js")
function2()
This sadly doesn't work and I have no idea how to solve this problem.
You can work with class approach or some older syntax. Any of these approaches results in the same thing, after all, the class syntax in JavaScript is just a thing for programmers, and does not affect the code at all. It is called syntax sugar.
See in the example below how to solve your problem without classes:
Export a object "container" with your functions:
Just as you referred in your example, 1st.js
export default {
functionOne: () => {
console.log("one");
},
functionTwo: (num) => {
console.log(num);
},
functionThree: ({number}) => {
console.log(number);
},
}
And import it with any name you want
...and so on, 2nd.js
import myFunctions from "../myFunctions";
const { functionOne, functionTwo, functionThree} = myFunctions;
functionOne();
functionTwo("two");
functionThree({number: "three"});

Redux Toolkit - Slice utility methods

I'm building a React app with redux-toolkit and I'm splitting my store into some slices with redux-toolkit's helper function createSlice.
Here it is a simple use case:
const sidebar = createSlice({
name: "sidebar",
initialState:
{
menus: {}, // Keep track of menus states (guid <-> open/close)
visible: true
},
reducers:
{
show(state, action)
{
state.visible = action.payload.visible;
},
setMenuOpen(state, action)
{
const { id, open } = action.payload;
state.menus[id] = open;
return state;
}
}
});
export default sidebar;
Everything works fine until I "add" actions (that change the store) to the slice but consider your team looking for an utility function "getMenuOpen": this method doesn't change the store (it's not an action and cannot be addeded to reducers object). You can of course read directly the data from the store (state.menus[<your_id>]) but consider a more complex example where manipulating the data requires some library imports, more complex code, etc...I want to modularize/hide each slice as much as possible.
Actually I'm using this workaround:
const sidebar = createSlice({ /* Same previous code... */ });
sidebar.methods =
{
getMenuOpen: (state, id) => state.menus[id]
};
export default sidebar;
The above code allows importing the slice from a component, mapStateToProps to the redux store, and invoke the utilty function getMenuOpen like this:
import sidebar from "./Sidebar.slice";
// Component declaration ...
const mapStateToProps = state => ({
sidebar: state.ui.layout.sidebar,
getMenuOpen(id)
{
return sidebar.methods.getMenuOpen(this.sidebar, id);
}
});
const mapDispatchToProps = dispatch => ({
setMenuOpen: (id, open) => dispatch(sidebar.actions.setMenuOpen({id, open}))
});
The ugly part is that I need to inject the slice node (this.sidebar) as fist param of getMenuOpen because it's not mapped (as for actions with reducers/actions) automatically from redux-toolkit.
So my question is: how can I clean my workaround in order to automatically map the store for utility functions? createSlice doesn't seem to support that but maybe some internal redux's api could help me in mapping my "slice.methods" automatically to the store.
Thanks

How do I test a function that is in a class with Jest

I have a function that is in a class :
Simplified version :
export class Button {
getAttributes(el) {
//random code that was removed for simplicity
return dataAttrs;
}
}
I was wondering how do I test this in Jest.
Here is what worked for me :
test('get attributes on element', () => {
let button= new Button();
var element = document.createElement('a');
element.setAttribute('href', 'https://www.google.ca/');
element.innerHTML = 'Test';
expect(breadcrumb.getAttributes(element)).toBe('Hello');
});
if there is simple class like the one that u define u can do:
it('We can check the class constructor', () => {
const classObject = new classObject();
expect(classObject ).toHaveBeenCalledTimes(1);
});
and use whatever the methods that Jest have.
But if there are complex classes and methods that ones are dependent from others i suggest you to read this and you can automatize it or can do it manually, mock the dependences and test it out.

Angular 7 HttpClient get - can you access and process the return object?

I know this is a general question but I have exhausted google and tried many approaches.Any feedback is appreciated.
The HTTPClient is Angular 5+ so it returns an object created from the response JSON data. I get a massive JSON response from an endpoint I have no control over and I want to use about 20% of the response in my app and ignore the rest.
I am really trying hard to avoid using a series of templates or export objects or whatever and trying to force this massive untyped Observable into a typed object with hundreds of fields many being Arrays. All I need for the app is just a Array of very small objects with 3 fields per object. The 3 fields are all over within the JSON response and I want to map them to my object .map only seems to work when you are using the full response object and I can't find an example where .map does custom work besides in the case where you are mapping a few fields to 1 object and I am trying to map to an Array of my small objects.
UPDATED
Basically I want this service to return an object of Type DislayData to the module that subscribes to it but I get just an Object back. This is not what I ultimately need to do but if I can prove I can map the body of the response to my needed return type I can then start to break down the response body and return an Array of the Type I really need based on my silly DisplayData object. Thanks again!
export interface DislayData {
body: any;
}
...
export class DataService {
constructor(private http: HttpClient) { }
/** GET data from the black box */
getData(): Observable<DislayData> {
return this.http.get<HttpResponse<any>>(searchUrl, { observe: 'response' })
.pipe(
map(res => {
return res.body as DislayData;
}
tap(res => console.log(//do stuff with entire respoonse also)),
catchError(err => this.handleError(err)));
}
private handleError(error: HttpErrorResponse) {
...
Do you know the structure of the answering object?
If yes, you can do something like this:
item$ = new BehaviorSubject<any>({});
item = {
foo: 'a',
bar: 'b',
iton: [1, 2, 3],
boo: {
far: 'c'
}
};
logNewItem() {
this.item$
.pipe(
map(response => {
if (response.foo
&& response.iton
&& response.iton.length >= 3
&& response.boo
&& response.boo.far) {
let newItem = {
foo: response.foo,
iton2: response.iton[2],
far: response.boo.far
};
console.log(newItem); // output: Object { foo: "a", iton2: 3, far: "c" }
}
})
)
.subscribe();
this.item$.next(this.item);
}
Basically, you can simply make sure the properties exist, call them directly and map them to a better fitting object.
I heavily recommend creating an interface for the object you're receiving and an interface or class for the object you're mapping to. In that case you can also write the code more compact like this:
[...]
map(response: MyAPIResponse => {
let newItem = new NewItem(response);
console.log(newItem); // output: Object { foo: "a", iton2: 3, far: "c" }
}
})
[...]
class NewItem {
foo: string;
iton2: string;
far: string;
constructor(apiResponse: MyAPIResponse) {
//Validate parameter first
this.foo = apiResponse.foo;
this.iton2 = apiResponse.iton[2];
this.far = apiResponse.boo.far;
and make your code a lot more readable.

Resources